// CC0 #define IMGUI_DEFINE_MATH_OPERATORS #include <imgui_internal.h> #define isdigit(c) (c >= '0' && c <= '9') namespace ImGui { float strToFloat (const char *s) // atof from minilibc { float a = 0.0; bool neg = false; int e = 0; int c; if (*s == '-') { neg = true; ++s; } while ((c = *s++) != '\0' && c != ' ' && isdigit(c)) { a = a*10.0f + (c - '0'); } if (c == '.') { while ((c = *s++) != '\0' && c != ' ' && isdigit(c)) { a = a*10.0f + (c - '0'); e = e-1; } } while (e < 0) { a *= 0.1f; e++; } return neg ? -a : a; } int tokenlLength (const char* str) { const char* c = str; for (; c - str < 16; ++c) { if (*c == ' ' || *c == '\0' ) { return int(c - str); } } return 16; } void DrawCmdList (ImDrawList* theDrawList, const ImVec2 thePivot, const char* theCmdList, const ImU32 theColor) { enum class State { None, RectFilled, // r left top right bottom Line, // l thickness p0.x p0.y p1.x p1.y }; State state = State::None; float cmdArgs[8] = {}; int cmdArgNum = 0; const char* c = theCmdList; while (*c) { switch (*c) { case ';': // execute command { switch (state) { case State::RectFilled: { theDrawList->AddRectFilled (thePivot + ImVec2 (cmdArgs[0], cmdArgs[1]), thePivot + ImVec2 (cmdArgs[2], cmdArgs[3]), theColor); break; } case State::Line: { theDrawList->AddLine (thePivot + ImVec2 (cmdArgs[1], cmdArgs[2]), thePivot + ImVec2 (cmdArgs[3], cmdArgs[4]), theColor, cmdArgs[0]); break; } default: break; } state = State::None; break; } case 'r': { state = State::RectFilled; cmdArgNum = 0; break; } case 'l': { state = State::Line; cmdArgNum = 0; break; } default: { cmdArgs[cmdArgNum++ % 8] = strToFloat (c); break; } } c += tokenlLength (c) + 1; // next cmd } } // Demo widget using DrawCmdList bool CircleVectorButton (const char* theID, const float theRadius, const char* theCmdList) { ImGuiWindow* window = ImGui::GetCurrentWindow(); if (window->SkipItems) return false; const ImGuiID id = window->GetID (theID); const ImVec2 size (theRadius * 2, theRadius * 2); const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size); const ImRect image_bb(window->DC.CursorPos, window->DC.CursorPos + size); ImGui::ItemSize(bb); if (!ImGui::ItemAdd(bb, id)) return false; bool hovered, held; bool pressed = ImGui::ButtonBehavior(bb, id, &hovered, &held); // Render const ImU32 col = ImGui::GetColorU32((held && hovered) ? ImGuiCol_ButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button); window->DrawList->AddCircleFilled (bb.Min + ImVec2 (theRadius, theRadius), theRadius, col, 24); DrawCmdList (window->DrawList, bb.GetCenter(), theCmdList, ImGui::GetColorU32 (ImGuiCol_Text)); return pressed; } }