Updated ImGui.
This commit is contained in:
parent
4091403934
commit
aa340f11de
57
3rdparty/dear-imgui/imgui.cpp
vendored
57
3rdparty/dear-imgui/imgui.cpp
vendored
@ -3058,7 +3058,7 @@ void ImGui::SetCurrentContext(ImGuiContext* ctx)
|
||||
// Helper function to verify ABI compatibility between caller code and compiled version of Dear ImGui.
|
||||
// Verify that the type sizes are matching between the calling file's compilation unit and imgui.cpp's compilation unit
|
||||
// If the user has inconsistent compilation settings, imgui configuration #define, packing pragma, etc. your user code
|
||||
// may see different structures thanwhat imgui.cpp sees, which is problematic.
|
||||
// may see different structures than what imgui.cpp sees, which is problematic.
|
||||
// We usually require settings to be in imconfig.h to make sure that they are accessible to all compilation units involved with Dear ImGui.
|
||||
bool ImGui::DebugCheckVersionAndDataLayout(const char* version, size_t sz_io, size_t sz_style, size_t sz_vec2, size_t sz_vec4, size_t sz_vert, size_t sz_idx)
|
||||
{
|
||||
@ -5505,10 +5505,10 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
||||
// We set this up after processing the resize grip so that our clip rectangle doesn't lag by a frame
|
||||
// Note that if our window is collapsed we will end up with an inverted (~null) clipping rectangle which is the correct behavior.
|
||||
const ImRect title_bar_rect = window->TitleBarRect();
|
||||
window->InnerMainRect.Min.x = title_bar_rect.Min.x + window->WindowBorderSize;
|
||||
window->InnerMainRect.Min.y = title_bar_rect.Max.y + window->MenuBarHeight() + (((flags & ImGuiWindowFlags_MenuBar) || !(flags & ImGuiWindowFlags_NoTitleBar)) ? style.FrameBorderSize : window->WindowBorderSize);
|
||||
window->InnerMainRect.Max.x = window->Pos.x + window->Size.x - ImMax(window->ScrollbarSizes.x, window->WindowBorderSize);
|
||||
window->InnerMainRect.Max.y = window->Pos.y + window->Size.y - ImMax(window->ScrollbarSizes.y, window->WindowBorderSize);
|
||||
window->InnerVisibleRect.Min.x = title_bar_rect.Min.x + window->WindowBorderSize;
|
||||
window->InnerVisibleRect.Min.y = title_bar_rect.Max.y + window->MenuBarHeight() + (((flags & ImGuiWindowFlags_MenuBar) || !(flags & ImGuiWindowFlags_NoTitleBar)) ? style.FrameBorderSize : window->WindowBorderSize);
|
||||
window->InnerVisibleRect.Max.x = window->Pos.x + window->Size.x - ImMax(window->ScrollbarSizes.x, window->WindowBorderSize);
|
||||
window->InnerVisibleRect.Max.y = window->Pos.y + window->Size.y - ImMax(window->ScrollbarSizes.y, window->WindowBorderSize);
|
||||
|
||||
// Outer host rectangle for drawing background and borders
|
||||
ImRect host_rect = ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & ImGuiWindowFlags_Popup) && !window_is_child_tooltip) ? parent_window->ClipRect : viewport_rect;
|
||||
@ -5520,10 +5520,10 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
||||
// Inner work/clipping rectangle will extend a little bit outside the work region.
|
||||
// This is to allow e.g. Selectable or CollapsingHeader or some separators to cover that space.
|
||||
// Force round operator last to ensure that e.g. (int)(max.x-min.x) in user's render code produce correct result.
|
||||
window->InnerWorkRect.Min.x = ImFloor(0.5f + window->InnerMainRect.Min.x + ImMax(0.0f, ImFloor(window->WindowPadding.x * 0.5f - window->WindowBorderSize)));
|
||||
window->InnerWorkRect.Min.y = ImFloor(0.5f + window->InnerMainRect.Min.y);
|
||||
window->InnerWorkRect.Max.x = ImFloor(0.5f + window->InnerMainRect.Max.x - ImMax(0.0f, ImFloor(window->WindowPadding.x * 0.5f - window->WindowBorderSize)));
|
||||
window->InnerWorkRect.Max.y = ImFloor(0.5f + window->InnerMainRect.Max.y);
|
||||
window->InnerWorkRect.Min.x = ImFloor(0.5f + window->InnerVisibleRect.Min.x + ImMax(0.0f, ImFloor(window->WindowPadding.x * 0.5f - window->WindowBorderSize)));
|
||||
window->InnerWorkRect.Min.y = ImFloor(0.5f + window->InnerVisibleRect.Min.y);
|
||||
window->InnerWorkRect.Max.x = ImFloor(0.5f + window->InnerVisibleRect.Max.x - ImMax(0.0f, ImFloor(window->WindowPadding.x * 0.5f - window->WindowBorderSize)));
|
||||
window->InnerWorkRect.Max.y = ImFloor(0.5f + window->InnerVisibleRect.Max.y);
|
||||
window->InnerWorkRectClipped = window->InnerWorkRect;
|
||||
window->InnerWorkRectClipped.ClipWithFull(host_rect);
|
||||
|
||||
@ -7832,7 +7832,7 @@ ImVec2 ImGui::GetNavInputAmount2d(ImGuiNavDirSourceFlags dir_sources, ImGuiInput
|
||||
// NB: We modify rect_rel by the amount we scrolled for, so it is immediately updated.
|
||||
static void NavScrollToBringItemIntoView(ImGuiWindow* window, const ImRect& item_rect)
|
||||
{
|
||||
ImRect window_rect(window->InnerMainRect.Min - ImVec2(1, 1), window->InnerMainRect.Max + ImVec2(1, 1));
|
||||
ImRect window_rect(window->InnerVisibleRect.Min - ImVec2(1, 1), window->InnerVisibleRect.Max + ImVec2(1, 1));
|
||||
//GetForegroundDrawList(window)->AddRect(window_rect.Min, window_rect.Max, IM_COL32_WHITE); // [DEBUG]
|
||||
if (window_rect.Contains(item_rect))
|
||||
return;
|
||||
@ -8106,7 +8106,7 @@ static void ImGui::NavUpdate()
|
||||
if (g.NavMoveRequest && g.NavMoveFromClampedRefRect && g.NavLayer == 0)
|
||||
{
|
||||
ImGuiWindow* window = g.NavWindow;
|
||||
ImRect window_rect_rel(window->InnerMainRect.Min - window->Pos - ImVec2(1,1), window->InnerMainRect.Max - window->Pos + ImVec2(1,1));
|
||||
ImRect window_rect_rel(window->InnerVisibleRect.Min - window->Pos - ImVec2(1,1), window->InnerVisibleRect.Max - window->Pos + ImVec2(1,1));
|
||||
if (!window_rect_rel.Contains(window->NavRectRel[g.NavLayer]))
|
||||
{
|
||||
float pad = window->CalcFontSize() * 0.5f;
|
||||
@ -8207,14 +8207,14 @@ static float ImGui::NavUpdatePageUpPageDown(int allowed_dir_flags)
|
||||
{
|
||||
// Fallback manual-scroll when window has no navigable item
|
||||
if (IsKeyPressed(g.IO.KeyMap[ImGuiKey_PageUp], true))
|
||||
SetWindowScrollY(window, window->Scroll.y - window->InnerMainRect.GetHeight());
|
||||
SetWindowScrollY(window, window->Scroll.y - window->InnerVisibleRect.GetHeight());
|
||||
else if (IsKeyPressed(g.IO.KeyMap[ImGuiKey_PageDown], true))
|
||||
SetWindowScrollY(window, window->Scroll.y + window->InnerMainRect.GetHeight());
|
||||
SetWindowScrollY(window, window->Scroll.y + window->InnerVisibleRect.GetHeight());
|
||||
}
|
||||
else
|
||||
{
|
||||
const ImRect& nav_rect_rel = window->NavRectRel[g.NavLayer];
|
||||
const float page_offset_y = ImMax(0.0f, window->InnerMainRect.GetHeight() - window->CalcFontSize() * 1.0f + nav_rect_rel.GetHeight());
|
||||
const float page_offset_y = ImMax(0.0f, window->InnerVisibleRect.GetHeight() - window->CalcFontSize() * 1.0f + nav_rect_rel.GetHeight());
|
||||
float nav_scoring_rect_offset_y = 0.0f;
|
||||
if (IsKeyPressed(g.IO.KeyMap[ImGuiKey_PageUp], true))
|
||||
{
|
||||
@ -9738,7 +9738,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
|
||||
return;
|
||||
}
|
||||
|
||||
enum { RT_OuterRect, RT_OuterRectClipped, RT_InnerMainRect, RT_InnerWorkRect, RT_InnerWorkRectClipped, RT_ContentsRegionRect, RT_ContentsFullRect };
|
||||
enum { RT_OuterRect, RT_OuterRectClipped, RT_InnerVisibleRect, RT_InnerWorkRect, RT_InnerWorkRectClipped, RT_ContentsRegionRect, RT_ContentsFullRect };
|
||||
static bool show_windows_begin_order = false;
|
||||
static bool show_windows_rects = false;
|
||||
static int show_windows_rect_type = RT_InnerWorkRect;
|
||||
@ -9754,6 +9754,18 @@ void ImGui::ShowMetricsWindow(bool* p_open)
|
||||
|
||||
struct Funcs
|
||||
{
|
||||
static ImRect GetRect(ImGuiWindow* window, int rect_type)
|
||||
{
|
||||
if (rect_type == RT_OuterRect) { return window->Rect(); }
|
||||
else if (rect_type == RT_OuterRectClipped) { return window->OuterRectClipped; }
|
||||
else if (rect_type == RT_InnerVisibleRect) { return window->InnerVisibleRect; }
|
||||
else if (rect_type == RT_InnerWorkRect) { return window->InnerWorkRect; }
|
||||
else if (rect_type == RT_InnerWorkRectClipped) { return window->InnerWorkRectClipped; }
|
||||
else if (rect_type == RT_ContentsRegionRect) { return window->ContentsRegionRect; }
|
||||
IM_ASSERT(0);
|
||||
return ImRect();
|
||||
}
|
||||
|
||||
static void NodeDrawList(ImGuiWindow* window, ImDrawList* draw_list, const char* label)
|
||||
{
|
||||
bool node_open = ImGui::TreeNode(draw_list, "%s: '%s' %d vtx, %d indices, %d cmds", label, draw_list->_OwnerName ? draw_list->_OwnerName : "", draw_list->VtxBuffer.Size, draw_list->IdxBuffer.Size, draw_list->CmdBuffer.Size);
|
||||
@ -9955,7 +9967,12 @@ void ImGui::ShowMetricsWindow(bool* p_open)
|
||||
ImGui::Checkbox("Show windows rectangles", &show_windows_rects);
|
||||
ImGui::SameLine();
|
||||
ImGui::SetNextItemWidth(ImGui::GetFontSize() * 12);
|
||||
show_windows_rects |= ImGui::Combo("##rects_type", &show_windows_rect_type, "OuterRect\0" "OuterRectClipped\0" "InnerMainRect\0" "InnerWorkRect\0" "InnerWorkRectClipped\0" "ContentsRegionRect\0");
|
||||
show_windows_rects |= ImGui::Combo("##rects_type", &show_windows_rect_type, "OuterRect\0" "OuterRectClipped\0" "InnerVisibleRect\0" "InnerWorkRect\0" "InnerWorkRectClipped\0" "ContentsRegionRect\0");
|
||||
if (show_windows_rects && g.NavWindow)
|
||||
{
|
||||
ImRect r = Funcs::GetRect(g.NavWindow, show_windows_rect_type);
|
||||
ImGui::BulletText("'%s': (%.1f,%.1f) (%.1f,%.1f) Size (%.1f,%.1f)", g.NavWindow->Name, r.Min.x, r.Min.y, r.Max.x, r.Max.y, r.GetWidth(), r.GetHeight());
|
||||
}
|
||||
ImGui::Checkbox("Show clipping rectangle when hovering ImDrawCmd node", &show_drawcmd_clip_rects);
|
||||
ImGui::TreePop();
|
||||
}
|
||||
@ -9970,13 +9987,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
|
||||
ImDrawList* draw_list = GetForegroundDrawList(window);
|
||||
if (show_windows_rects)
|
||||
{
|
||||
ImRect r;
|
||||
if (show_windows_rect_type == RT_OuterRect) { r = window->Rect(); }
|
||||
else if (show_windows_rect_type == RT_OuterRectClipped) { r = window->OuterRectClipped; }
|
||||
else if (show_windows_rect_type == RT_InnerMainRect) { r = window->InnerMainRect; }
|
||||
else if (show_windows_rect_type == RT_InnerWorkRect) { r = window->InnerWorkRect; }
|
||||
else if (show_windows_rect_type == RT_InnerWorkRectClipped) { r = window->InnerWorkRectClipped; }
|
||||
else if (show_windows_rect_type == RT_ContentsRegionRect) { r = window->ContentsRegionRect; }
|
||||
ImRect r = Funcs::GetRect(window, show_windows_rect_type);
|
||||
draw_list->AddRect(r.Min, r.Max, IM_COL32(255, 0, 128, 255));
|
||||
}
|
||||
if (show_windows_begin_order && !(window->Flags & ImGuiWindowFlags_ChildWindow))
|
||||
|
10
3rdparty/dear-imgui/imgui.h
vendored
10
3rdparty/dear-imgui/imgui.h
vendored
@ -2078,11 +2078,14 @@ struct ImFontAtlas
|
||||
IMGUI_API const ImWchar* GetGlyphRangesVietnamese(); // Default + Vietname characters
|
||||
|
||||
//-------------------------------------------
|
||||
// Custom Rectangles/Glyphs API
|
||||
// [BETA] Custom Rectangles/Glyphs API
|
||||
//-------------------------------------------
|
||||
|
||||
// You can request arbitrary rectangles to be packed into the atlas, for your own purposes. After calling Build(), you can query the rectangle position and render your pixels.
|
||||
// You can also request your rectangles to be mapped as font glyph (given a font + Unicode point), so you can render e.g. custom colorful icons and use them as regular glyphs.
|
||||
// You can request arbitrary rectangles to be packed into the atlas, for your own purposes.
|
||||
// After calling Build(), you can query the rectangle position and render your pixels.
|
||||
// You can also request your rectangles to be mapped as font glyph (given a font + Unicode point),
|
||||
// so you can render e.g. custom colorful icons and use them as regular glyphs.
|
||||
// Read misc/fonts/README.txt for more details about using colorful icons.
|
||||
struct CustomRect
|
||||
{
|
||||
unsigned int ID; // Input // User ID. Use <0x10000 to map into a font glyph, >=0x10000 for other/internal/custom texture data.
|
||||
@ -2094,7 +2097,6 @@ struct ImFontAtlas
|
||||
CustomRect() { ID = 0xFFFFFFFF; Width = Height = 0; X = Y = 0xFFFF; GlyphAdvanceX = 0.0f; GlyphOffset = ImVec2(0,0); Font = NULL; }
|
||||
bool IsPacked() const { return X != 0xFFFF; }
|
||||
};
|
||||
|
||||
IMGUI_API int AddCustomRectRegular(unsigned int id, int width, int height); // Id needs to be >= 0x10000. Id >= 0x80000000 are reserved for ImGui and ImDrawList
|
||||
IMGUI_API int AddCustomRectFontGlyph(ImFont* font, ImWchar id, int width, int height, float advance_x, const ImVec2& offset = ImVec2(0,0)); // Id needs to be < 0x10000 to register a rectangle to map into a specific font.
|
||||
const CustomRect* GetCustomRectByIndex(int index) const { if (index < 0) return NULL; return &CustomRects[index]; }
|
||||
|
12
3rdparty/dear-imgui/imgui_internal.h
vendored
12
3rdparty/dear-imgui/imgui_internal.h
vendored
@ -361,6 +361,12 @@ enum ImGuiSelectableFlagsPrivate_
|
||||
ImGuiSelectableFlags_AllowItemOverlap = 1 << 24
|
||||
};
|
||||
|
||||
// Extend ImGuiTreeNodeFlags_
|
||||
enum ImGuiTreeNodeFlagsPrivate_
|
||||
{
|
||||
ImGuiTreeNodeFlags_ClipLabelForTrailingButton = 1 << 20
|
||||
};
|
||||
|
||||
enum ImGuiSeparatorFlags_
|
||||
{
|
||||
ImGuiSeparatorFlags_None = 0,
|
||||
@ -1249,8 +1255,8 @@ struct IMGUI_API ImGuiWindow
|
||||
ImVec2 Size; // Current size (==SizeFull or collapsed title bar size)
|
||||
ImVec2 SizeFull; // Size when non collapsed
|
||||
ImVec2 SizeFullAtLastBegin; // Copy of SizeFull at the end of Begin. This is the reference value we'll use on the next frame to decide if we need scrollbars.
|
||||
ImVec2 SizeContents; // Size of contents (== extents reach of the drawing cursor) from previous frame. Include decoration, window title, border, menu, etc.
|
||||
ImVec2 SizeContentsExplicit; // Size of contents explicitly set by the user via SetNextWindowContentSize()
|
||||
ImVec2 SizeContents; // Size of contents (== extents reach of the drawing cursor) from previous frame. FIXME: Include decoration, window title, border, menu, etc. Ideally should remove them from this value?
|
||||
ImVec2 SizeContentsExplicit; // Size of contents explicitly set by the user via SetNextWindowContentSize(). EXCLUDE decorations. Making this not consistent with the above!
|
||||
ImVec2 WindowPadding; // Window padding at the time of begin.
|
||||
float WindowRounding; // Window rounding at the time of begin.
|
||||
float WindowBorderSize; // Window border size at the time of begin.
|
||||
@ -1292,7 +1298,7 @@ struct IMGUI_API ImGuiWindow
|
||||
ImVector<ImGuiID> IDStack; // ID stack. ID are hashes seeded with the value at the top of the stack
|
||||
ImRect ClipRect; // Current clipping rectangle. = DrawList->clip_rect_stack.back(). Scissoring / clipping rectangle. x1, y1, x2, y2.
|
||||
ImRect OuterRectClipped; // == WindowRect just after setup in Begin(). == window->Rect() for root window.
|
||||
ImRect InnerMainRect; //
|
||||
ImRect InnerVisibleRect; // Inner visible rectangle
|
||||
ImRect InnerWorkRect; // == InnerMainRect minus WindowPadding.x
|
||||
ImRect InnerWorkRectClipped; // == InnerMainRect minus WindowPadding.x, clipped within viewport or parent clip rect.
|
||||
ImRect ContentsRegionRect; // FIXME: This is currently confusing/misleading. Maximum visible content position ~~ Pos + (SizeContentsExplicit ? SizeContentsExplicit : Size - ScrollbarSizes) - CursorStartPos, per axis
|
||||
|
22
3rdparty/dear-imgui/imgui_widgets.cpp
vendored
22
3rdparty/dear-imgui/imgui_widgets.cpp
vendored
@ -888,14 +888,14 @@ void ImGui::Scrollbar(ImGuiAxis axis)
|
||||
ImRect bb;
|
||||
if (axis == ImGuiAxis_X)
|
||||
{
|
||||
bb.Min = ImVec2(window->InnerMainRect.Min.x, window->InnerMainRect.Max.y);
|
||||
bb.Max = ImVec2(window->InnerMainRect.Max.x, outer_rect.Max.y - window->WindowBorderSize);
|
||||
bb.Min = ImVec2(window->InnerVisibleRect.Min.x, window->InnerVisibleRect.Max.y);
|
||||
bb.Max = ImVec2(window->InnerVisibleRect.Max.x, outer_rect.Max.y - window->WindowBorderSize);
|
||||
rounding_corners |= ImDrawCornerFlags_BotLeft;
|
||||
}
|
||||
else
|
||||
{
|
||||
bb.Min = ImVec2(window->InnerMainRect.Max.x, window->InnerMainRect.Min.y);
|
||||
bb.Max = ImVec2(outer_rect.Max.x - window->WindowBorderSize, window->InnerMainRect.Max.y);
|
||||
bb.Min = ImVec2(window->InnerVisibleRect.Max.x, window->InnerVisibleRect.Min.y);
|
||||
bb.Max = ImVec2(outer_rect.Max.x - window->WindowBorderSize, window->InnerVisibleRect.Max.y);
|
||||
rounding_corners |= ((window->Flags & ImGuiWindowFlags_NoTitleBar) && !(window->Flags & ImGuiWindowFlags_MenuBar)) ? ImDrawCornerFlags_TopRight : 0;
|
||||
}
|
||||
ScrollbarEx(bb, id, axis, &window->Scroll[axis], window->SizeFull[axis] - other_scrollbar_size, window->SizeContents[axis], rounding_corners);
|
||||
@ -5146,8 +5146,8 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
|
||||
if (display_frame)
|
||||
{
|
||||
// Framed header expand a little outside the default padding
|
||||
frame_bb.Min.x -= (float)(int)(window->WindowPadding.x*0.5f) - 1;
|
||||
frame_bb.Max.x += (float)(int)(window->WindowPadding.x*0.5f) - 1;
|
||||
frame_bb.Min.x -= (float)(int)(window->WindowPadding.x * 0.5f) - 1;
|
||||
frame_bb.Max.x += (float)(int)(window->WindowPadding.x * 0.5f) - 1;
|
||||
}
|
||||
|
||||
const float text_offset_x = (g.FontSize + (display_frame ? padding.x*3 : padding.x*2)); // Collapser arrow width + Spacing
|
||||
@ -5244,6 +5244,8 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
|
||||
RenderFrame(frame_bb.Min, frame_bb.Max, col, true, style.FrameRounding);
|
||||
RenderNavHighlight(frame_bb, id, nav_highlight_flags);
|
||||
RenderArrow(frame_bb.Min + ImVec2(padding.x, text_base_offset_y), is_open ? ImGuiDir_Down : ImGuiDir_Right, 1.0f);
|
||||
if (flags & ImGuiTreeNodeFlags_ClipLabelForTrailingButton)
|
||||
frame_bb.Max.x -= g.FontSize + style.FramePadding.x;
|
||||
if (g.LogEnabled)
|
||||
{
|
||||
// NB: '##' is normally used to hide text (as a library-wide feature), so we need to specify the text range to make sure the ## aren't stripped out here.
|
||||
@ -5370,7 +5372,8 @@ bool ImGui::CollapsingHeader(const char* label, bool* p_open, ImGuiTreeNodeFlags
|
||||
return false;
|
||||
|
||||
ImGuiID id = window->GetID(label);
|
||||
bool is_open = TreeNodeBehavior(id, flags | ImGuiTreeNodeFlags_CollapsingHeader | (p_open ? ImGuiTreeNodeFlags_AllowItemOverlap : 0), label);
|
||||
flags |= ImGuiTreeNodeFlags_CollapsingHeader | (p_open ? ImGuiTreeNodeFlags_AllowItemOverlap | ImGuiTreeNodeFlags_ClipLabelForTrailingButton : 0);
|
||||
bool is_open = TreeNodeBehavior(id, flags, label);
|
||||
if (p_open)
|
||||
{
|
||||
// Create a small overlapping close button
|
||||
@ -5379,8 +5382,9 @@ bool ImGui::CollapsingHeader(const char* label, bool* p_open, ImGuiTreeNodeFlags
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiItemHoveredDataBackup last_item_backup;
|
||||
float button_size = g.FontSize;
|
||||
ImVec2 button_pos = ImVec2(ImMin(window->DC.LastItemRect.Max.x, window->ClipRect.Max.x) - g.Style.FramePadding.x * 2.0f - button_size, window->DC.LastItemRect.Min.y);
|
||||
if (CloseButton(window->GetID((void*)((intptr_t)id + 1)), button_pos))
|
||||
float button_x = ImMax(window->DC.LastItemRect.Min.x, window->DC.LastItemRect.Max.x - g.Style.FramePadding.x * 2.0f - button_size);
|
||||
float button_y = window->DC.LastItemRect.Min.y;
|
||||
if (CloseButton(window->GetID((void*)((intptr_t)id + 1)), ImVec2(button_x, button_y)))
|
||||
*p_open = false;
|
||||
last_item_backup.Restore();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user