Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions dearpygui/_dearpygui.pyi

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 9 additions & 7 deletions dearpygui/_dearpygui_RTD.py

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 10 additions & 8 deletions dearpygui/dearpygui.py

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions src/dearpygui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,9 @@ GetModuleConstants()
ModuleConstants.push_back({"mvScrollDirection_Horizontal", mvScrollDirection_Horizontal });
ModuleConstants.push_back({"mvScrollDirection_Vertical", mvScrollDirection_Vertical });

ModuleConstants.push_back({"mvLoadInd_DottedCircle", mvLoadingIndicator::Style_DottedCircle });
ModuleConstants.push_back({"mvLoadInd_Ring", mvLoadingIndicator::Style_Ring });

ModuleConstants.push_back({"mvPlatform_Windows", 0L });
ModuleConstants.push_back({"mvPlatform_Apple", 1L });
ModuleConstants.push_back({"mvPlatform_Linux", 2L });
Expand Down
14 changes: 7 additions & 7 deletions src/mvAppItem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4542,13 +4542,13 @@ DearPyGui::GetEntityParser(mvAppItemType type)
MV_PARSER_ARG_POS)
);

args.push_back({ mvPyDataType::Integer, "style", mvArgType::KEYWORD_ARG, "0", "0 is rotating dots style, 1 is rotating bar style." });
args.push_back({ mvPyDataType::Integer, "circle_count", mvArgType::KEYWORD_ARG, "8", "Number of dots show if dots or size of circle if circle." });
args.push_back({ mvPyDataType::Float, "speed", mvArgType::KEYWORD_ARG, "1.0", "Speed the anamation will rotate." });
args.push_back({ mvPyDataType::Float, "radius", mvArgType::KEYWORD_ARG, "3.0", "Radius size of the loading indicator." });
args.push_back({ mvPyDataType::Float, "thickness", mvArgType::KEYWORD_ARG, "1.0", "Thickness of the circles or line." });
args.push_back({ mvPyDataType::IntList, "color", mvArgType::KEYWORD_ARG, "(51, 51, 55, 255)", "Color of the growing center circle." });
args.push_back({ mvPyDataType::IntList, "secondary_color", mvArgType::KEYWORD_ARG, "(29, 151, 236, 103)", "Background of the dots in dot mode." });
args.push_back({ mvPyDataType::Integer, "style", mvArgType::KEYWORD_ARG, "0", "mvLoadInd_DottedCircle is rotating dots style, mvLoadInd_Ring is rotating bar style." });
args.push_back({ mvPyDataType::Integer, "circle_count", mvArgType::KEYWORD_ARG, "8", "DottedCircle style: number of dots to show." });
args.push_back({ mvPyDataType::Float, "speed", mvArgType::KEYWORD_ARG, "1.0", "Speed with which the animation will rotate." });
args.push_back({ mvPyDataType::Float, "radius", mvArgType::KEYWORD_ARG, "3.0", "Scale factor for the loading indicator radius. The size of the indicator is determined by font size and this scale factor." });
args.push_back({ mvPyDataType::Float, "thickness", mvArgType::KEYWORD_ARG, "1.0", "Ring style: scale factor of line thickness; thickness=1 corresponds to line width being 1/8 of the ring diameter." });
args.push_back({ mvPyDataType::IntList, "color", mvArgType::KEYWORD_ARG, "None", "Main color of the indicator. If omitted, the color for mvThemeCol_Button will be used." });
args.push_back({ mvPyDataType::IntList, "secondary_color", mvArgType::KEYWORD_ARG, "None", "DottedCircle style: color of 'inactive' dots. If omitted, the color for mvThemeCol_ButtonHovered will be used." });

setup.about = "Adds a rotating animated loading symbol.";
break;
Expand Down
39 changes: 34 additions & 5 deletions src/mvLoadingIndicator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,33 @@ void mvLoadingIndicator::draw(ImDrawList* drawlist, float x, float y)
{
ScopedID id(uuid);

if (_style == 0)
switch (_style)
{
case Style_OldDottedCircle:
LoadingIndicatorCircle(config.specifiedLabel.c_str(), _radius, _mainColor, _optionalColor, _circleCount, _speed);
else
break;
case Style_OldRing:
LoadingIndicatorCircle2(config.specifiedLabel.c_str(), _radius, _thickness, _mainColor);
break;
case Style_DottedCircle:
// This is to align the indicator body to text rather than to framed rect
// (can be useful with radius=1).
ImGui::AlignTextToFramePadding();
LoadingIndicatorCircle(config.specifiedLabel.c_str(), _radius, _mainColor, _optionalColor, _circleCount, _speed);
break;
case Style_Ring:
{
const float pixSize = (_radius > 0? _radius : 1.f) * ImGui::GetTextLineHeight();
// `thickness=1` corresponds to line thickness being 1/4 of the ring radius,
// i.e. 1/8 of the diameter (pixSize).
const float pixThickness = (_thickness > 0? _thickness : 1.f) * pixSize * 0.125f;
// This is to align the indicator body to text rather than to framed rect
// (can be useful with radius=1).
ImGui::AlignTextToFramePadding();
LoadingIndicatorRing(config.specifiedLabel.c_str(), pixSize, pixThickness, _speed, _mainColor);
}
break;
}
}

//-----------------------------------------------------------------------------
Expand Down Expand Up @@ -98,13 +121,19 @@ void mvLoadingIndicator::handleSpecificKeywordArgs(PyObject* dict)
if (dict == nullptr)
return;

if (PyObject* item = PyDict_GetItemString(dict, "style")) _style = ToInt(item);
if (PyObject* item = PyDict_GetItemString(dict, "style")) _style = static_cast<Style>(ToInt(item));
if (PyObject* item = PyDict_GetItemString(dict, "circle_count")) _circleCount = ToInt(item);
if (PyObject* item = PyDict_GetItemString(dict, "radius")) _radius = ToFloat(item);
if (PyObject* item = PyDict_GetItemString(dict, "thickness")) _thickness = ToFloat(item);
if (PyObject* item = PyDict_GetItemString(dict, "speed")) _speed = ToFloat(item);
if (PyObject* item = PyDict_GetItemString(dict, "color")) _mainColor = ToColor(item);
if (PyObject* item = PyDict_GetItemString(dict, "secondary_color")) _optionalColor = ToColor(item);
if (PyObject* item = PyDict_GetItemString(dict, "color"))
{
_mainColor = (item != Py_None)? ToColor(item) : mvColor();
}
if (PyObject* item = PyDict_GetItemString(dict, "secondary_color"))
{
_optionalColor = (item != Py_None)? ToColor(item) : mvColor();
}
}

void mvLoadingIndicator::getSpecificConfiguration(PyObject* dict)
Expand Down
13 changes: 10 additions & 3 deletions src/mvLoadingIndicator.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,21 @@ class mvLoadingIndicator : public mvAppItem
void handleSpecificKeywordArgs(PyObject* dict) override;
void getSpecificConfiguration(PyObject* dict) override;

enum Style {
Style_OldDottedCircle = 0,
Style_OldRing,
Style_DottedCircle,
Style_Ring,
};

private:

int _style = 0;
Style _style = Style_DottedCircle;
int _circleCount = 8;
float _radius = 3.0f;
float _speed = 1.0f;
float _thickness = 1.0f;
mvColor _mainColor = mvColor(51, 51, 55, 255);
mvColor _optionalColor = mvColor(29, 151, 236, 103);
mvColor _mainColor;
mvColor _optionalColor;

};
68 changes: 60 additions & 8 deletions src/mvLoadingIndicatorCustom.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,19 @@ void LoadingIndicatorCircle(const char* label, float indicatorRadiusFactor,

if (circle_count <= 0) circle_count = 12;
if (indicatorRadiusFactor <= 0.f) indicatorRadiusFactor = 1.f;
if (!pOptionalMainColor) pOptionalMainColor = &style.Colors[ImGuiCol_Button];
if (!pOptionalBackdropColor) pOptionalBackdropColor = &style.Colors[ImGuiCol_ButtonHovered];
if (!pOptionalMainColor || pOptionalMainColor->w < 0) pOptionalMainColor = &style.Colors[ImGuiCol_Button];
if (!pOptionalBackdropColor || pOptionalBackdropColor->w < 0) pOptionalBackdropColor = &style.Colors[ImGuiCol_ButtonHovered];

const float lineHeight = ImGui::GetTextLineHeight(); // or GetTextLineHeight() or GetTextLineHeightWithSpacing() ?
float indicatorRadiusPixels = indicatorRadiusFactor * lineHeight * 0.5f;

const ImVec2 pos = window->DC.CursorPos;
const ImVec2 pos(window->DC.CursorPos.x, window->DC.CursorPos.y + window->DC.CurrLineTextBaseOffset);
const float circle_radius = indicatorRadiusPixels / 8.f;
indicatorRadiusPixels -= 2.0f * circle_radius;
const ImRect bb(pos, ImVec2(pos.x + indicatorRadiusPixels * 2.f + 4.f * circle_radius,
pos.y + indicatorRadiusPixels * 2.f + 4.f * circle_radius));
ImGui::ItemSize(bb, style.FramePadding.y);
if (!ImGui::ItemAdd(bb, id)) {
ImGui::ItemSize(bb, 0.0f);
if (!ImGui::ItemAdd(bb, id, nullptr, ImGuiItemFlags_NoNav)) {
return;
}
const float base_num_segments = circle_radius * 1.f;
Expand Down Expand Up @@ -69,7 +69,7 @@ void LoadingIndicatorCircle2(const char* label, float indicatorRadiusFactor, flo

if (indicatorRadiusFactor <= 0.f) indicatorRadiusFactor = 1.f;
if (indicatorRadiusThicknessFactor <= 0.f) indicatorRadiusThicknessFactor = 1.f;
if (!pOptionalColor) pOptionalColor = &style.Colors[ImGuiCol_Button];
if (!pOptionalColor || pOptionalColor->w < 0) pOptionalColor = &style.Colors[ImGuiCol_Button];
const ImU32 color = ImGui::GetColorU32(*pOptionalColor);

const float lineHeight = ImGui::GetTextLineHeight(); // or GetTextLineHeight() or GetTextLineHeightWithSpacing() ?
Expand All @@ -96,7 +96,7 @@ void LoadingIndicatorCircle2(const char* label, float indicatorRadiusFactor, flo

int num_segments = 30;

int start = abs(ImSin(g.Time * 1.8f) * (num_segments - 5));
int start = abs((int)(ImSin(g.Time * 1.8f) * (num_segments - 5)));

const float a_min = IM_PI * 2.0f * ((float)start) / (float)num_segments;
const float a_max = IM_PI * 2.0f * ((float)num_segments - 3) / (float)num_segments;
Expand All @@ -110,4 +110,56 @@ void LoadingIndicatorCircle2(const char* label, float indicatorRadiusFactor, flo
}

window->DrawList->PathStroke(color, false, indicatorThicknessPixels);
}
}

// A corrected version of LoadingIndicatorCircle2 that calculates sizes/positions properly.
void LoadingIndicatorRing(const char* label, float size, float thickness, float speed, const ImVec4* pOptionalColor) {
ImGuiWindow* window = ImGui::GetCurrentWindow();
if (window->SkipItems)
return;

ImGuiContext& g = *GImGui;
const ImGuiStyle& style = g.Style;
const ImGuiID id = window->GetID(label);

if (!pOptionalColor || pOptionalColor->w < 0) pOptionalColor = &style.Colors[ImGuiCol_Button];
const ImU32 color = ImGui::GetColorU32(*pOptionalColor);

float radius = size * 0.5f;

const ImVec2 pos(window->DC.CursorPos.x, window->DC.CursorPos.y + window->DC.CurrLineTextBaseOffset);
const ImRect bb(pos, ImVec2(pos.x + size, pos.y + size));

ImGui::ItemSize(bb, 0.0f);
if (!ImGui::ItemAdd(bb, id, nullptr, ImGuiItemFlags_NoNav))
return;

// Render
window->DrawList->PathClear();

//int num_segments = radius/8.f;
//if (num_segments<4) num_segments=4;

int num_segments = 30;

float t = g.Time * speed;

// With this formula it looks very close to the original LoadingIndicatorCircle2
// but does not have visual artifacts (jitter of the ring tail when it slows down).
float start = 0.5f * (1 - ImSin(t*3.0f)) * (num_segments - 5);

const float a_min = IM_PI * 2.0f * start / (float)num_segments;
const float a_max = IM_PI * 2.0f * ((float)num_segments - 2) / (float)num_segments;

const ImVec2 centre = ImVec2(pos.x + radius, pos.y + radius);

radius -= thickness * 0.5f;

for (int i = 0; i < num_segments; i++) {
const float a = a_min + ((float)i / (float)num_segments) * (a_max - a_min);
window->DrawList->PathLineTo(ImVec2(centre.x + ImCos(a + t * 8) * radius,
centre.y + ImSin(a + t * 8) * radius));
}

window->DrawList->PathStroke(color, false, thickness);
}
4 changes: 3 additions & 1 deletion src/mvLoadingIndicatorCustom.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,6 @@ void LoadingIndicatorCircle(const char* label, float indicatorRadiusFactor = 1.f

// Posted by @zfedoran here: https://github.com/ocornut/imgui/issues/1901
// Sligthly modified to provide default behaviour with default args
void LoadingIndicatorCircle2(const char* label, float indicatorRadiusFactor = 1.f, float indicatorRadiusThicknessFactor = 1.f, const ImVec4* pOptionalColor = NULL);
void LoadingIndicatorCircle2(const char* label, float indicatorRadiusFactor = 1.f, float indicatorRadiusThicknessFactor = 1.f, const ImVec4* pOptionalColor = NULL);

void LoadingIndicatorRing(const char* label, float size, float thickness, float speed = 1.f, const ImVec4* pOptionalColor = nullptr);
Loading