b751f98e91
* ui/ux: Initial recreation of the hex editor view * ui/ux: Added back support for editing cells * ux: Make scrolling and selecting bytes feel nice again * ui/ux: Improved byte selecting, added footer * sys: Make math evaluator more generic to support integer only calculations * patterns: Moved value formatting into pattern language * ui/ux: Added Goto and Search popups, improved selection * ui: Added better tooltips for bookmarks and patterns * sys: Use worse hex search algorithm on macOS Sadly it still doesn't support `std::boyer_moore_horsepool_searcher` * ui: Added back missing events, menu items and shortcuts * fix: Bookmark highlighting being rendered off by one * fix: Various macOS build errors * fix: size_t is not u64 on macos * fix: std::fmod and std::pow not working with integer types on macos * fix: Missing semicolons * sys: Added proper integer pow function * ui: Added back support for custom encodings * fix: Editor not jumping to selection when selection gets changed * ui: Turn Hexii setting into a data visualizer * sys: Added back remaining shortcuts * sys: Remove old hex editor files * sys: Moved more legacy things away from the hex editor view, updated localization * fix: Hex editor scrolling behaving weirdly and inconsistently * sys: Cleaned up Hex editor code * sys: Added selection color setting, localized all new settings * fix: Search feature not working correctly * ui: Replace custom ImGui::Disabled function with native ImGui ones * ui: Fix bookmark tooltip rendering issues * fix: Another size_t not being 64 bit issue on MacOS
593 lines
24 KiB
C++
593 lines
24 KiB
C++
#include <hex/ui/imgui_imhex_extensions.h>
|
|
|
|
#include <imgui.h>
|
|
#include <imgui_freetype.h>
|
|
#define IMGUI_DEFINE_MATH_OPERATORS
|
|
#include <imgui_internal.h>
|
|
#undef IMGUI_DEFINE_MATH_OPERATORS
|
|
|
|
#define STB_IMAGE_IMPLEMENTATION
|
|
#include <stb_image.h>
|
|
|
|
#include <string>
|
|
|
|
#include <imgui_impl_opengl3_loader.h>
|
|
|
|
namespace ImGui {
|
|
|
|
int UpdateStringSizeCallback(ImGuiInputTextCallbackData *data) {
|
|
if (data->EventFlag == ImGuiInputTextFlags_CallbackResize) {
|
|
auto &string = *static_cast<std::string *>(data->UserData);
|
|
|
|
string.resize(data->BufSize);
|
|
data->Buf = string.data();
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
bool IconHyperlink(const char *icon, const char *label, const ImVec2 &size_arg, ImGuiButtonFlags flags) {
|
|
ImGuiWindow *window = GetCurrentWindow();
|
|
if (window->SkipItems)
|
|
return false;
|
|
|
|
ImGuiContext &g = *GImGui;
|
|
const ImGuiID id = window->GetID(label);
|
|
ImVec2 label_size = CalcTextSize(icon, NULL, false);
|
|
label_size.x += CalcTextSize(" ", NULL, false).x + CalcTextSize(label, NULL, false).x;
|
|
|
|
ImVec2 pos = window->DC.CursorPos;
|
|
ImVec2 size = CalcItemSize(size_arg, label_size.x, label_size.y);
|
|
|
|
const ImRect bb(pos, pos + size);
|
|
if (!ItemAdd(bb, id))
|
|
return false;
|
|
|
|
if (g.LastItemData.InFlags & ImGuiItemFlags_ButtonRepeat)
|
|
flags |= ImGuiButtonFlags_Repeat;
|
|
bool hovered, held;
|
|
bool pressed = ButtonBehavior(bb, id, &hovered, &held, flags);
|
|
|
|
// Render
|
|
const ImU32 col = hovered ? GetColorU32(ImGuiCol_ButtonHovered) : GetColorU32(ImGuiCol_ButtonActive);
|
|
PushStyleColor(ImGuiCol_Text, ImU32(col));
|
|
|
|
Text("%s %s", icon, label);
|
|
GetWindowDrawList()->AddLine(ImVec2(pos.x, pos.y + size.y), pos + size, ImU32(col));
|
|
PopStyleColor();
|
|
|
|
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.LastItemStatusFlags);
|
|
return pressed;
|
|
}
|
|
|
|
bool Hyperlink(const char *label, const ImVec2 &size_arg, ImGuiButtonFlags flags) {
|
|
ImGuiWindow *window = GetCurrentWindow();
|
|
if (window->SkipItems)
|
|
return false;
|
|
|
|
ImGuiContext &g = *GImGui;
|
|
const ImGuiID id = window->GetID(label);
|
|
const ImVec2 label_size = CalcTextSize(label, NULL, true);
|
|
|
|
ImVec2 pos = window->DC.CursorPos;
|
|
ImVec2 size = CalcItemSize(size_arg, label_size.x, label_size.y);
|
|
|
|
const ImRect bb(pos, pos + size);
|
|
if (!ItemAdd(bb, id))
|
|
return false;
|
|
|
|
if (g.LastItemData.InFlags & ImGuiItemFlags_ButtonRepeat)
|
|
flags |= ImGuiButtonFlags_Repeat;
|
|
bool hovered, held;
|
|
bool pressed = ButtonBehavior(bb, id, &hovered, &held, flags);
|
|
|
|
// Render
|
|
const ImU32 col = hovered ? GetColorU32(ImGuiCol_ButtonHovered) : GetColorU32(ImGuiCol_ButtonActive);
|
|
PushStyleColor(ImGuiCol_Text, ImU32(col));
|
|
TextEx(label, NULL, ImGuiTextFlags_NoWidthForLargeClippedText); // Skip formatting
|
|
GetWindowDrawList()->AddLine(ImVec2(pos.x, pos.y + size.y), pos + size, ImU32(col));
|
|
PopStyleColor();
|
|
|
|
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.LastItemStatusFlags);
|
|
return pressed;
|
|
}
|
|
|
|
bool BulletHyperlink(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;
|
|
ImVec2 size = CalcItemSize(size_arg, label_size.x, label_size.y) + ImVec2(g.FontSize + style.FramePadding.x * 2, 0.0f);
|
|
|
|
const ImRect bb(pos, pos + size);
|
|
ItemSize(size, 0);
|
|
if (!ItemAdd(bb, id))
|
|
return false;
|
|
|
|
if (g.LastItemData.InFlags & ImGuiItemFlags_ButtonRepeat)
|
|
flags |= ImGuiButtonFlags_Repeat;
|
|
bool hovered, held;
|
|
bool pressed = ButtonBehavior(bb, id, &hovered, &held, flags);
|
|
|
|
// Render
|
|
const ImU32 col = hovered ? GetColorU32(ImGuiCol_ButtonHovered) : GetColorU32(ImGuiCol_ButtonActive);
|
|
PushStyleColor(ImGuiCol_Text, ImU32(col));
|
|
RenderBullet(window->DrawList, bb.Min + ImVec2(style.FramePadding.x, g.FontSize * 0.5f), col);
|
|
RenderText(bb.Min + ImVec2(g.FontSize * 0.5 + style.FramePadding.x, 0.0f), label, nullptr, false);
|
|
GetWindowDrawList()->AddLine(bb.Min + ImVec2(g.FontSize * 0.5 + style.FramePadding.x, size.y), pos + size - ImVec2(g.FontSize * 0.5 + style.FramePadding.x, 0), ImU32(col));
|
|
PopStyleColor();
|
|
|
|
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.LastItemStatusFlags);
|
|
return pressed;
|
|
}
|
|
|
|
bool DescriptionButton(const char *label, const char *description, 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 text_size = CalcTextSize((std::string(label) + "\n " + std::string(description)).c_str(), NULL, true);
|
|
const ImVec2 label_size = CalcTextSize(label, NULL, true);
|
|
|
|
ImVec2 pos = window->DC.CursorPos;
|
|
if ((flags & ImGuiButtonFlags_AlignTextBaseLine) && style.FramePadding.y < window->DC.CurrLineTextBaseOffset) // 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.CurrLineTextBaseOffset - style.FramePadding.y;
|
|
ImVec2 size = CalcItemSize(size_arg, text_size.x + style.FramePadding.x * 4.0f, text_size.y + style.FramePadding.y * 4.0f);
|
|
|
|
const ImRect bb(pos, pos + size);
|
|
ItemSize(size, style.FramePadding.y);
|
|
if (!ItemAdd(bb, id))
|
|
return false;
|
|
|
|
if (g.LastItemData.InFlags & ImGuiItemFlags_ButtonRepeat)
|
|
flags |= ImGuiButtonFlags_Repeat;
|
|
bool hovered, held;
|
|
bool pressed = ButtonBehavior(bb, id, &hovered, &held, flags);
|
|
|
|
ImGui::PushStyleVar(ImGuiStyleVar_ButtonTextAlign, ImVec2(0.0, 0.5));
|
|
|
|
// Render
|
|
const ImU32 col = GetCustomColorU32((held && hovered) ? ImGuiCustomCol_DescButtonActive : hovered ? ImGuiCustomCol_DescButtonHovered
|
|
: ImGuiCustomCol_DescButton);
|
|
RenderNavHighlight(bb, id);
|
|
RenderFrame(bb.Min, bb.Max, col, true, style.FrameRounding);
|
|
PushStyleColor(ImGuiCol_Text, GetColorU32(ImGuiCol_ButtonActive));
|
|
RenderTextWrapped(bb.Min + style.FramePadding * 2, label, nullptr, CalcWrapWidthForPos(window->DC.CursorPos, window->DC.TextWrapPos));
|
|
PopStyleColor();
|
|
PushStyleColor(ImGuiCol_Text, GetColorU32(ImGuiCol_Text));
|
|
RenderTextClipped(bb.Min + style.FramePadding * 2 + ImVec2(style.FramePadding.x * 2, label_size.y), bb.Max - style.FramePadding, description, NULL, &text_size, style.ButtonTextAlign, &bb);
|
|
PopStyleColor();
|
|
|
|
ImGui::PopStyleVar();
|
|
|
|
// Automatically close popups
|
|
// if (pressed && !(flags & ImGuiButtonFlags_DontClosePopups) && (window->Flags & ImGuiWindowFlags_Popup))
|
|
// CloseCurrentPopup();
|
|
|
|
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.LastItemStatusFlags);
|
|
return pressed;
|
|
}
|
|
|
|
void UnderlinedText(const char *label, ImColor color, const ImVec2 &size_arg) {
|
|
ImGuiWindow *window = GetCurrentWindow();
|
|
|
|
const ImVec2 label_size = CalcTextSize(label, NULL, true);
|
|
|
|
ImVec2 pos = window->DC.CursorPos;
|
|
ImVec2 size = CalcItemSize(size_arg, label_size.x, label_size.y);
|
|
|
|
PushStyleColor(ImGuiCol_Text, ImU32(color));
|
|
TextEx(label, NULL, ImGuiTextFlags_NoWidthForLargeClippedText); // Skip formatting
|
|
GetWindowDrawList()->AddLine(ImVec2(pos.x, pos.y + size.y), pos + size, ImU32(color));
|
|
PopStyleColor();
|
|
}
|
|
|
|
void TextSpinner(const char *label) {
|
|
ImGui::Text("[%c] %s", "|/-\\"[ImU32(ImGui::GetTime() * 20) % 4], label);
|
|
}
|
|
|
|
void Header(const char *label, bool firstEntry) {
|
|
if (!firstEntry)
|
|
ImGui::NewLine();
|
|
ImGui::TextUnformatted(label);
|
|
ImGui::Separator();
|
|
}
|
|
|
|
void HeaderColored(const char *label, ImColor color, bool firstEntry) {
|
|
if (!firstEntry)
|
|
ImGui::NewLine();
|
|
ImGui::TextFormattedColored(color, "{}", label);
|
|
ImGui::Separator();
|
|
}
|
|
|
|
void InfoTooltip(const char *text) {
|
|
static double lastMoveTime;
|
|
static ImGuiID lastHoveredID;
|
|
|
|
double currTime = ImGui::GetTime();
|
|
ImGuiID hoveredID = ImGui::GetHoveredID();
|
|
|
|
if (IsItemHovered() && (currTime - lastMoveTime) >= 0.5 && hoveredID == lastHoveredID) {
|
|
BeginTooltip();
|
|
TextUnformatted(text);
|
|
EndTooltip();
|
|
}
|
|
|
|
if (hoveredID != lastHoveredID) {
|
|
lastMoveTime = currTime;
|
|
}
|
|
lastHoveredID = hoveredID;
|
|
}
|
|
|
|
ImU32 GetCustomColorU32(ImGuiCustomCol idx, float alpha_mul) {
|
|
auto &customData = *static_cast<ImHexCustomData *>(GImGui->IO.UserData);
|
|
ImVec4 c = customData.Colors[idx];
|
|
c.w *= GImGui->Style.Alpha * alpha_mul;
|
|
return ColorConvertFloat4ToU32(c);
|
|
}
|
|
|
|
ImVec4 GetCustomColorVec4(ImGuiCustomCol idx, float alpha_mul) {
|
|
auto &customData = *static_cast<ImHexCustomData *>(GImGui->IO.UserData);
|
|
ImVec4 c = customData.Colors[idx];
|
|
c.w *= GImGui->Style.Alpha * alpha_mul;
|
|
return c;
|
|
}
|
|
|
|
void StyleCustomColorsDark() {
|
|
auto &colors = static_cast<ImHexCustomData *>(GImGui->IO.UserData)->Colors;
|
|
|
|
colors[ImGuiCustomCol_DescButton] = ImColor(20, 20, 20);
|
|
colors[ImGuiCustomCol_DescButtonHovered] = ImColor(40, 40, 40);
|
|
colors[ImGuiCustomCol_DescButtonActive] = ImColor(60, 60, 60);
|
|
|
|
colors[ImGuiCustomCol_ToolbarGray] = ImColor(230, 230, 230);
|
|
colors[ImGuiCustomCol_ToolbarRed] = ImColor(231, 76, 60);
|
|
colors[ImGuiCustomCol_ToolbarYellow] = ImColor(241, 196, 15);
|
|
colors[ImGuiCustomCol_ToolbarGreen] = ImColor(56, 139, 66);
|
|
colors[ImGuiCustomCol_ToolbarBlue] = ImColor(6, 83, 155);
|
|
colors[ImGuiCustomCol_ToolbarPurple] = ImColor(103, 42, 120);
|
|
colors[ImGuiCustomCol_ToolbarBrown] = ImColor(219, 179, 119);
|
|
|
|
colors[ImGuiCustomCol_Highlight] = ImColor(77, 198, 155);
|
|
}
|
|
|
|
void StyleCustomColorsLight() {
|
|
auto &colors = static_cast<ImHexCustomData *>(GImGui->IO.UserData)->Colors;
|
|
|
|
colors[ImGuiCustomCol_DescButton] = ImColor(230, 230, 230);
|
|
colors[ImGuiCustomCol_DescButtonHovered] = ImColor(210, 210, 210);
|
|
colors[ImGuiCustomCol_DescButtonActive] = ImColor(190, 190, 190);
|
|
|
|
colors[ImGuiCustomCol_ToolbarGray] = ImColor(25, 25, 25);
|
|
colors[ImGuiCustomCol_ToolbarRed] = ImColor(231, 76, 60);
|
|
colors[ImGuiCustomCol_ToolbarYellow] = ImColor(241, 196, 15);
|
|
colors[ImGuiCustomCol_ToolbarGreen] = ImColor(56, 139, 66);
|
|
colors[ImGuiCustomCol_ToolbarBlue] = ImColor(6, 83, 155);
|
|
colors[ImGuiCustomCol_ToolbarPurple] = ImColor(103, 42, 120);
|
|
colors[ImGuiCustomCol_ToolbarBrown] = ImColor(219, 179, 119);
|
|
|
|
colors[ImGuiCustomCol_Highlight] = ImColor(41, 151, 112);
|
|
}
|
|
|
|
void StyleCustomColorsClassic() {
|
|
auto &colors = static_cast<ImHexCustomData *>(GImGui->IO.UserData)->Colors;
|
|
|
|
colors[ImGuiCustomCol_DescButton] = ImColor(40, 40, 80);
|
|
colors[ImGuiCustomCol_DescButtonHovered] = ImColor(60, 60, 100);
|
|
colors[ImGuiCustomCol_DescButtonActive] = ImColor(80, 80, 120);
|
|
|
|
colors[ImGuiCustomCol_ToolbarGray] = ImColor(230, 230, 230);
|
|
colors[ImGuiCustomCol_ToolbarRed] = ImColor(231, 76, 60);
|
|
colors[ImGuiCustomCol_ToolbarYellow] = ImColor(241, 196, 15);
|
|
colors[ImGuiCustomCol_ToolbarGreen] = ImColor(56, 139, 66);
|
|
colors[ImGuiCustomCol_ToolbarBlue] = ImColor(6, 83, 155);
|
|
colors[ImGuiCustomCol_ToolbarPurple] = ImColor(103, 42, 120);
|
|
colors[ImGuiCustomCol_ToolbarBrown] = ImColor(219, 179, 119);
|
|
|
|
colors[ImGuiCustomCol_Highlight] = ImColor(77, 198, 155);
|
|
}
|
|
|
|
Texture LoadImageFromPath(const char *path) {
|
|
int imageWidth = 0;
|
|
int imageHeight = 0;
|
|
|
|
unsigned char *imageData = stbi_load(path, &imageWidth, &imageHeight, nullptr, 4);
|
|
if (imageData == nullptr)
|
|
return { nullptr, -1, -1 };
|
|
|
|
|
|
GLuint texture;
|
|
glGenTextures(1, &texture);
|
|
glBindTexture(GL_TEXTURE_2D, texture);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
|
|
#if defined(GL_UNPACK_ROW_LENGTH)
|
|
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
|
#endif
|
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, imageWidth, imageHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageData);
|
|
stbi_image_free(imageData);
|
|
|
|
return { reinterpret_cast<ImTextureID>(static_cast<intptr_t>(texture)), imageWidth, imageHeight };
|
|
}
|
|
|
|
Texture LoadImageFromMemory(const ImU8 *buffer, int size) {
|
|
int imageWidth = 0;
|
|
int imageHeight = 0;
|
|
|
|
|
|
unsigned char *imageData = stbi_load_from_memory(buffer, size, &imageWidth, &imageHeight, nullptr, 4);
|
|
if (imageData == nullptr)
|
|
return { nullptr, -1, -1 };
|
|
|
|
GLuint texture;
|
|
glGenTextures(1, &texture);
|
|
glBindTexture(GL_TEXTURE_2D, texture);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
|
|
#if defined(GL_UNPACK_ROW_LENGTH)
|
|
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
|
#endif
|
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, imageWidth, imageHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageData);
|
|
stbi_image_free(imageData);
|
|
|
|
return { reinterpret_cast<ImTextureID>(static_cast<intptr_t>(texture)), imageWidth, imageHeight };
|
|
}
|
|
|
|
void UnloadImage(Texture &texture) {
|
|
if (texture.textureId == nullptr)
|
|
return;
|
|
|
|
auto glTextureId = static_cast<GLuint>(reinterpret_cast<intptr_t>(texture.textureId));
|
|
glDeleteTextures(1, &glTextureId);
|
|
|
|
texture = { nullptr, 0, 0 };
|
|
}
|
|
|
|
void OpenPopupInWindow(const char *window_name, const char *popup_name) {
|
|
if (ImGui::Begin(window_name)) {
|
|
ImGui::OpenPopup(popup_name);
|
|
}
|
|
ImGui::End();
|
|
}
|
|
|
|
|
|
bool TitleBarButton(const char *label, ImVec2 size_arg) {
|
|
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;
|
|
|
|
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(size, style.FramePadding.y);
|
|
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, style.FrameRounding);
|
|
RenderTextClipped(bb.Min + style.FramePadding * ImVec2(1, 2), bb.Max - style.FramePadding, label, NULL, &label_size, style.ButtonTextAlign, &bb);
|
|
|
|
// Automatically close popups
|
|
// if (pressed && !(flags & ImGuiButtonFlags_DontClosePopups) && (window->Flags & ImGuiWindowFlags_Popup))
|
|
// CloseCurrentPopup();
|
|
|
|
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.LastItemStatusFlags);
|
|
return pressed;
|
|
}
|
|
|
|
bool ToolBarButton(const char *symbol, ImVec4 color) {
|
|
ImGuiWindow *window = GetCurrentWindow();
|
|
if (window->SkipItems)
|
|
return false;
|
|
|
|
color.w = 1.0F;
|
|
|
|
ImGuiContext &g = *GImGui;
|
|
const ImGuiStyle &style = g.Style;
|
|
const ImGuiID id = window->GetID(symbol);
|
|
const ImVec2 label_size = CalcTextSize(symbol, NULL, true);
|
|
|
|
ImVec2 pos = window->DC.CursorPos;
|
|
|
|
ImVec2 size = CalcItemSize(ImVec2(1, 1) * ImGui::GetCurrentWindow()->MenuBarHeight(), label_size.x + style.FramePadding.x * 2.0f, label_size.y + style.FramePadding.y * 2.0f);
|
|
|
|
const ImRect bb(pos, pos + size);
|
|
ItemSize(size, style.FramePadding.y);
|
|
if (!ItemAdd(bb, id))
|
|
return false;
|
|
|
|
bool hovered, held;
|
|
bool pressed = ButtonBehavior(bb, id, &hovered, &held);
|
|
|
|
PushStyleColor(ImGuiCol_Text, color);
|
|
|
|
// Render
|
|
const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_ScrollbarGrabActive : hovered ? ImGuiCol_ScrollbarGrabHovered
|
|
: ImGuiCol_MenuBarBg);
|
|
RenderNavHighlight(bb, id);
|
|
RenderFrame(bb.Min, bb.Max, col, false, style.FrameRounding);
|
|
RenderTextClipped(bb.Min + style.FramePadding * ImVec2(1, 2), bb.Max - style.FramePadding, symbol, NULL, &label_size, style.ButtonTextAlign, &bb);
|
|
|
|
PopStyleColor();
|
|
|
|
// Automatically close popups
|
|
// if (pressed && !(flags & ImGuiButtonFlags_DontClosePopups) && (window->Flags & ImGuiWindowFlags_Popup))
|
|
// CloseCurrentPopup();
|
|
|
|
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.LastItemStatusFlags);
|
|
return pressed;
|
|
}
|
|
|
|
bool IconButton(const char *symbol, ImVec4 color, ImVec2 size_arg) {
|
|
ImGuiWindow *window = GetCurrentWindow();
|
|
if (window->SkipItems)
|
|
return false;
|
|
|
|
color.w = 1.0F;
|
|
|
|
ImGuiContext &g = *GImGui;
|
|
const ImGuiStyle &style = g.Style;
|
|
const ImGuiID id = window->GetID(symbol);
|
|
const ImVec2 label_size = CalcTextSize(symbol, NULL, true);
|
|
|
|
ImVec2 pos = window->DC.CursorPos;
|
|
|
|
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(size, style.FramePadding.y);
|
|
if (!ItemAdd(bb, id))
|
|
return false;
|
|
|
|
bool hovered, held;
|
|
bool pressed = ButtonBehavior(bb, id, &hovered, &held);
|
|
|
|
PushStyleColor(ImGuiCol_Text, color);
|
|
|
|
// Render
|
|
const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered
|
|
: ImGuiCol_Button);
|
|
RenderNavHighlight(bb, id);
|
|
RenderFrame(bb.Min, bb.Max, col, false, style.FrameRounding);
|
|
RenderTextClipped(bb.Min + style.FramePadding * ImVec2(1, 2), bb.Max - style.FramePadding, symbol, NULL, &label_size, style.ButtonTextAlign, &bb);
|
|
|
|
PopStyleColor();
|
|
|
|
// Automatically close popups
|
|
// if (pressed && !(flags & ImGuiButtonFlags_DontClosePopups) && (window->Flags & ImGuiWindowFlags_Popup))
|
|
// CloseCurrentPopup();
|
|
|
|
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.LastItemStatusFlags);
|
|
return pressed;
|
|
}
|
|
|
|
bool InputIntegerPrefix(const char *label, const char *prefix, u64 *value, ImGuiInputTextFlags flags) {
|
|
auto window = ImGui::GetCurrentWindow();
|
|
const ImGuiID id = window->GetID(label);
|
|
const ImGuiStyle &style = GImGui->Style;
|
|
|
|
|
|
const ImVec2 label_size = CalcTextSize(label, nullptr, true);
|
|
const ImVec2 frame_size = CalcItemSize(ImVec2(0, 0), CalcTextSize(prefix).x, label_size.y + style.FramePadding.y * 2.0f);
|
|
const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + frame_size);
|
|
|
|
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + frame_size.x);
|
|
|
|
char buf[64];
|
|
DataTypeFormatString(buf, IM_ARRAYSIZE(buf), ImGuiDataType_U64, value, "%llX");
|
|
|
|
bool value_changed = false;
|
|
if (InputTextEx(label, nullptr, buf, IM_ARRAYSIZE(buf), ImVec2(CalcItemWidth() - frame_size.x, label_size.y + style.FramePadding.y * 2.0f), flags))
|
|
value_changed = DataTypeApplyOpFromText(buf, GImGui->InputTextState.InitialTextA.Data, ImGuiDataType_U64, value, "%llX");
|
|
|
|
if (value_changed)
|
|
MarkItemEdited(GImGui->LastItemData.ID);
|
|
|
|
RenderNavHighlight(frame_bb, id);
|
|
RenderFrame(frame_bb.Min, frame_bb.Max, GetColorU32(ImGuiCol_FrameBg), true, style.FrameRounding);
|
|
|
|
ImGui::PushStyleVar(ImGuiStyleVar_Alpha, 0.6F);
|
|
RenderText(ImVec2(frame_bb.Min.x + style.FramePadding.x, frame_bb.Min.y + style.FramePadding.y), prefix);
|
|
ImGui::PopStyleVar();
|
|
|
|
return value_changed;
|
|
}
|
|
|
|
bool InputHexadecimal(const char *label, u64 *value, ImGuiInputTextFlags flags) {
|
|
return InputIntegerPrefix(label, "0x", value, flags | ImGuiInputTextFlags_CharsHexadecimal);
|
|
}
|
|
|
|
void SmallProgressBar(float fraction, float yOffset) {
|
|
ImGuiWindow *window = GetCurrentWindow();
|
|
if (window->SkipItems)
|
|
return;
|
|
|
|
ImGuiContext &g = *GImGui;
|
|
const ImGuiStyle &style = g.Style;
|
|
|
|
ImVec2 pos = window->DC.CursorPos + ImVec2(0, yOffset);
|
|
ImVec2 size = CalcItemSize(ImVec2(100, 5), 100, g.FontSize + style.FramePadding.y * 2.0f);
|
|
ImRect bb(pos, pos + size);
|
|
ItemSize(size, 0);
|
|
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));
|
|
RenderRectFilledRangeH(window->DrawList, bb, GetColorU32(ImGuiCol_PlotHistogram), 0.0f, fraction, style.FrameRounding);
|
|
}
|
|
|
|
bool InputText(const char *label, std::string &buffer, ImGuiInputTextFlags flags) {
|
|
return ImGui::InputText(label, buffer.data(), buffer.size() + 1, ImGuiInputTextFlags_CallbackResize | flags, ImGui::UpdateStringSizeCallback, &buffer);
|
|
}
|
|
|
|
bool InputTextMultiline(const char *label, std::string &buffer, const ImVec2 &size, ImGuiInputTextFlags flags) {
|
|
return ImGui::InputTextMultiline(label, buffer.data(), buffer.size() + 1, size, ImGuiInputTextFlags_CallbackResize | flags, ImGui::UpdateStringSizeCallback, &buffer);
|
|
}
|
|
|
|
bool InputScalarCallback(const char* label, ImGuiDataType data_type, void* p_data, const char* format, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data) {
|
|
ImGuiWindow* window = GetCurrentWindow();
|
|
if (window->SkipItems)
|
|
return false;
|
|
|
|
ImGuiContext& g = *GImGui;
|
|
|
|
if (format == NULL)
|
|
format = DataTypeGetInfo(data_type)->PrintFmt;
|
|
|
|
char buf[64];
|
|
DataTypeFormatString(buf, IM_ARRAYSIZE(buf), data_type, p_data, format);
|
|
|
|
bool value_changed = false;
|
|
if ((flags & (ImGuiInputTextFlags_CharsHexadecimal | ImGuiInputTextFlags_CharsScientific)) == 0)
|
|
flags |= ImGuiInputTextFlags_CharsDecimal;
|
|
flags |= ImGuiInputTextFlags_AutoSelectAll;
|
|
flags |= ImGuiInputTextFlags_NoMarkEdited; // We call MarkItemEdited() ourselves by comparing the actual data rather than the string.
|
|
|
|
if (InputText(label, buf, IM_ARRAYSIZE(buf), flags, callback, user_data))
|
|
value_changed = DataTypeApplyOpFromText(buf, g.InputTextState.InitialTextA.Data, data_type, p_data, format);
|
|
|
|
if (value_changed)
|
|
MarkItemEdited(g.LastItemData.ID);
|
|
|
|
return value_changed;
|
|
}
|
|
|
|
void HideTooltip() {
|
|
char window_name[16];
|
|
ImFormatString(window_name, IM_ARRAYSIZE(window_name), "##Tooltip_%02d", GImGui->TooltipOverrideCount);
|
|
if (ImGuiWindow* window = FindWindowByName(window_name); window != nullptr) {
|
|
if (window->Active)
|
|
window->Hidden = true;
|
|
}
|
|
}
|
|
|
|
} |