Compare commits

...

6 Commits

7 changed files with 285 additions and 23 deletions

View File

@ -40,6 +40,8 @@ Breaking changes:
Other Changes:
- Stack Tool: Added option to copy item path to clipboard. (#4631)
- Misc: Added constexpr to ImVec2/ImVec4 inline constructors. (#4995) [@Myriachan]
- ImVector: Fixed erase() with empty range. (#5009) [@thedmd]
- Drawlist: Fixed PathArcTo() emitting terminating vertices too close to arc vertices. (#4993) [@thedmd]

View File

@ -81,12 +81,12 @@
//---- Define constructor and implicit cast operators to convert back<>forth between your math types and ImVec2/ImVec4.
// This will be inlined as part of ImVec2 and ImVec4 class declarations.
/*
#define IM_VEC2_CLASS_EXTRA \
ImVec2(const MyVec2& f) { x = f.x; y = f.y; } \
#define IM_VEC2_CLASS_EXTRA \
constexpr ImVec2(const MyVec2& f) : x(f.x), y(f.y) {} \
operator MyVec2() const { return MyVec2(x,y); }
#define IM_VEC4_CLASS_EXTRA \
ImVec4(const MyVec4& f) { x = f.x; y = f.y; z = f.z; w = f.w; } \
#define IM_VEC4_CLASS_EXTRA \
constexpr ImVec4(const MyVec4& f) : x(f.x), y(f.y), z(f.z), w(f.w) {} \
operator MyVec4() const { return MyVec4(x,y,z,w); }
*/

View File

@ -1180,7 +1180,7 @@ void ImGuiIO::AddInputCharacter(unsigned int c)
return;
ImGuiInputEvent e;
e.Type = ImGuiInputEventType_Char;
e.Type = ImGuiInputEventType_Text;
e.Source = ImGuiInputSource_Keyboard;
e.Text.Char = c;
g.InputEventsQueue.push_back(e);
@ -7882,7 +7882,7 @@ void ImGui::UpdateInputEvents(bool trickle_fast_inputs)
}
}
}
else if (e->Type == ImGuiInputEventType_Char)
else if (e->Type == ImGuiInputEventType_Text)
{
// Trickling Rule: Stop processing queued events if keys/mouse have been interacted with
if (trickle_fast_inputs && (key_changed || mouse_button_changed != 0 || mouse_moved || mouse_wheeled))

12
imgui.h
View File

@ -65,7 +65,7 @@ Index of this file:
// Version
// (Integer encoded as XYYZZ for use in #if preprocessor conditionals. Work in progress versions typically starts at XYY99 then bounce up to XYY00, XYY01 etc. when release tagging happens)
#define IMGUI_VERSION "1.88 WIP"
#define IMGUI_VERSION_NUM 18703
#define IMGUI_VERSION_NUM 18704
#define IMGUI_CHECKVERSION() ImGui::DebugCheckVersionAndDataLayout(IMGUI_VERSION, sizeof(ImGuiIO), sizeof(ImGuiStyle), sizeof(ImVec2), sizeof(ImVec4), sizeof(ImDrawVert), sizeof(ImDrawIdx))
#define IMGUI_HAS_TABLE
@ -249,8 +249,8 @@ IM_MSVC_RUNTIME_CHECKS_OFF
struct ImVec2
{
float x, y;
ImVec2() { x = y = 0.0f; }
ImVec2(float _x, float _y) { x = _x; y = _y; }
constexpr ImVec2() : x(0.0f), y(0.0f) { }
constexpr ImVec2(float _x, float _y) : x(_x), y(_y) { }
float operator[] (size_t idx) const { IM_ASSERT(idx <= 1); return (&x)[idx]; } // We very rarely use this [] operator, the assert overhead is fine.
float& operator[] (size_t idx) { IM_ASSERT(idx <= 1); return (&x)[idx]; } // We very rarely use this [] operator, the assert overhead is fine.
#ifdef IM_VEC2_CLASS_EXTRA
@ -261,9 +261,9 @@ struct ImVec2
// ImVec4: 4D vector used to store clipping rectangles, colors etc. [Compile-time configurable type]
struct ImVec4
{
float x, y, z, w;
ImVec4() { x = y = z = w = 0.0f; }
ImVec4(float _x, float _y, float _z, float _w) { x = _x; y = _y; z = _z; w = _w; }
float x, y, z, w;
constexpr ImVec4() : x(0.0f), y(0.0f), z(0.0f), w(0.0f) { }
constexpr ImVec4(float _x, float _y, float _z, float _w) : x(_x), y(_y), z(_z), w(_w) { }
#ifdef IM_VEC4_CLASS_EXTRA
IM_VEC4_CLASS_EXTRA // Define additional constructors and implicit cast operators in imconfig.h to convert back and forth between your math types and ImVec4.
#endif

View File

@ -716,7 +716,7 @@ void ImDrawList::PrimQuadUV(const ImVec2& a, const ImVec2& b, const ImVec2& c, c
#define IM_FIXNORMAL2F_MAX_INVLEN2 100.0f // 500.0f (see #4053, #3366)
#define IM_FIXNORMAL2F(VX,VY) { float d2 = VX*VX + VY*VY; if (d2 > 0.000001f) { float inv_len2 = 1.0f / d2; if (inv_len2 > IM_FIXNORMAL2F_MAX_INVLEN2) inv_len2 = IM_FIXNORMAL2F_MAX_INVLEN2; VX *= inv_len2; VY *= inv_len2; } } (void)0
// TODO: Thickness anti-aliased lines cap are missing their AA fringe.
// FIXME: Thickness anti-aliased lines cap are missing their AA fringe.
// We avoid using the ImVec2 math operators here to reduce cost to a minimum for debug/non-inlined builds.
void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32 col, ImDrawFlags flags, float thickness)
{
@ -728,6 +728,264 @@ void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32
const int count = closed ? points_count : points_count - 1; // The number of line segments we need to draw
const bool thick_line = (thickness > _FringeScale);
// (Intentionally incorrect indentation to avoid altering)
bool USE_NEW_CODE = true;
//bool USE_NEW_CODE = ImGui::GetIO().KeyShift;
if (USE_NEW_CODE)
{
const float AA_SIZE = 1.0f;
const ImU32 col_trans = col & ~IM_COL32_A_MASK;
const bool antialias = (Flags & ImDrawListFlags_AntiAliasedLines) != 0;
if (antialias && !thick_line)
{
// Anti-aliased stroke approximation
const int idx_count = count * 12;
const int vtx_count = count * 6; // FIXME-OPT: Not sharing edges
PrimReserve(idx_count, vtx_count);
ImU32 col_faded = col;
if (thickness < 1.0f)
col_faded = col_trans | ((int)(((col >> IM_COL32_A_SHIFT) & 0xFF) * thickness) << IM_COL32_A_SHIFT);
for (int i1 = 0; i1 < count; i1++)
{
const int i2 = (i1 + 1) == points_count ? 0 : i1 + 1;
const ImVec2& p1 = points[i1];
const ImVec2& p2 = points[i2];
float dx = p2.x - p1.x;
float dy = p2.y - p1.y;
IM_NORMALIZE2F_OVER_ZERO(dx, dy);
dx *= AA_SIZE;
dy *= AA_SIZE;
_VtxWritePtr[0].pos.x = p1.x + dy; _VtxWritePtr[0].pos.y = p1.y - dx; _VtxWritePtr[0].uv = opaque_uv; _VtxWritePtr[0].col = col_trans;
_VtxWritePtr[1].pos.x = p1.x; _VtxWritePtr[1].pos.y = p1.y; _VtxWritePtr[1].uv = opaque_uv; _VtxWritePtr[1].col = col_faded;
_VtxWritePtr[2].pos.x = p1.x - dy; _VtxWritePtr[2].pos.y = p1.y + dx; _VtxWritePtr[2].uv = opaque_uv; _VtxWritePtr[2].col = col_trans;
_VtxWritePtr[3].pos.x = p2.x + dy; _VtxWritePtr[3].pos.y = p2.y - dx; _VtxWritePtr[3].uv = opaque_uv; _VtxWritePtr[3].col = col_trans;
_VtxWritePtr[4].pos.x = p2.x; _VtxWritePtr[4].pos.y = p2.y; _VtxWritePtr[4].uv = opaque_uv; _VtxWritePtr[4].col = col_faded;
_VtxWritePtr[5].pos.x = p2.x - dy; _VtxWritePtr[5].pos.y = p2.y + dx; _VtxWritePtr[5].uv = opaque_uv; _VtxWritePtr[5].col = col_trans;
_VtxWritePtr += 6;
_IdxWritePtr[0] = (ImDrawIdx)(_VtxCurrentIdx); _IdxWritePtr[1] = (ImDrawIdx)(_VtxCurrentIdx + 1); _IdxWritePtr[2] = (ImDrawIdx)(_VtxCurrentIdx + 4);
_IdxWritePtr[3] = (ImDrawIdx)(_VtxCurrentIdx); _IdxWritePtr[4] = (ImDrawIdx)(_VtxCurrentIdx + 4); _IdxWritePtr[5] = (ImDrawIdx)(_VtxCurrentIdx + 3);
_IdxWritePtr[6] = (ImDrawIdx)(_VtxCurrentIdx + 1); _IdxWritePtr[7] = (ImDrawIdx)(_VtxCurrentIdx + 2); _IdxWritePtr[8] = (ImDrawIdx)(_VtxCurrentIdx + 5);
_IdxWritePtr[9] = (ImDrawIdx)(_VtxCurrentIdx + 1); _IdxWritePtr[10]= (ImDrawIdx)(_VtxCurrentIdx + 5); _IdxWritePtr[11]= (ImDrawIdx)(_VtxCurrentIdx + 4);
_IdxWritePtr += 12;
_VtxCurrentIdx += 6;
}
}
else
{
// Precise line with bevels on acute angles
const int max_n_vtx = antialias ? 6 : 3;
const int max_n_idx = 3 * (antialias ? 9 : 3);
const int vtx_count = points_count * max_n_vtx;
const int idx_count = count * max_n_idx;
PrimReserve(idx_count, vtx_count);
const float half_thickness = (antialias ? thickness - AA_SIZE : thickness) * 0.5f;
const float half_thickness_aa = half_thickness + AA_SIZE;
const unsigned int first_vtx_idx = _VtxCurrentIdx;
// Declare temporary variables in outer scope. Declared without a default value would trigger static analyser, and doing it in inner-scope would be more wasteful.
float mlx, mly, mrx, mry; // Left and right miters
float mlax = 0.0f, mlay = 0.0f, mrax = 0.0f, mray = 0.0f; // Left and right miters including anti-aliasing
float b1x = 0.0f, b1y = 0.0f, b2x = 0.0f, b2y = 0.0f; // First and second bevel point
float b1ax = 0.0f, b1ay = 0.0f, b2ax = 0.0f, b2ay = 0.0f; // First and second bevel point including anti-aliasing
float sqlen1 = 0.0f;
float dx1 = 0.0f, dy1 = 0.0f;
if (closed)
{
dx1 = points[0].x - points[points_count - 1].x;
dy1 = points[0].y - points[points_count - 1].y;
sqlen1 = dx1 * dx1 + dy1 * dy1;
IM_NORMALIZE2F_OVER_ZERO(dx1, dy1);
}
for (int i1 = 0; i1 < points_count; i1++)
{
const int i2 = (i1 + 1 == points_count) ? 0 : i1 + 1;
const ImVec2& p1 = points[i1];
const ImVec2& p2 = points[i2];
float dx2 = p1.x - p2.x;
float dy2 = p1.y - p2.y;
float sqlen2 = dx2 * dx2 + dy2 * dy2;
IM_NORMALIZE2F_OVER_ZERO(dx2, dy2);
if (!closed && i1 == 0)
{
dx1 = -dx2;
dy1 = -dy2;
sqlen1 = sqlen2;
}
else if (!closed && i1 == points_count - 1)
{
dx2 = -dx1;
dy2 = -dy1;
sqlen2 = sqlen1;
}
float miter_l_recip = dx1 * dy2 - dy1 * dx2;
const bool bevel = (dx1 * dx2 + dy1 * dy2) > 1e-5f;
if (ImFabs(miter_l_recip) > 1e-5f)
{
float miter_l = half_thickness / miter_l_recip;
// Limit (inner) miter so it doesn't shoot away when miter is longer than adjacent line segments on acute angles
if (bevel)
{
// This is too aggressive (not exactly precise)
float min_sqlen = sqlen1 > sqlen2 ? sqlen2 : sqlen1;
float miter_sqlen = ((dx1 + dx2) * (dx1 + dx2) + (dy1 + dy2) * (dy1 + dy2)) * miter_l * miter_l;
if (miter_sqlen > min_sqlen)
miter_l *= ImSqrt(min_sqlen / miter_sqlen);
}
mlx = p1.x - (dx1 + dx2) * miter_l;
mly = p1.y - (dy1 + dy2) * miter_l;
mrx = p1.x + (dx1 + dx2) * miter_l;
mry = p1.y + (dy1 + dy2) * miter_l;
if (antialias)
{
float miter_al = half_thickness_aa / miter_l_recip;
mlax = p1.x - (dx1 + dx2) * miter_al;
mlay = p1.y - (dy1 + dy2) * miter_al;
mrax = p1.x + (dx1 + dx2) * miter_al;
mray = p1.y + (dy1 + dy2) * miter_al;
}
}
else
{
// Avoid degeneracy for (nearly) straight lines
mlx = p1.x + dy1 * half_thickness;
mly = p1.y - dx1 * half_thickness;
mrx = p1.x - dy1 * half_thickness;
mry = p1.y + dx1 * half_thickness;
if (antialias)
{
mlax = p1.x + dy1 * half_thickness_aa;
mlay = p1.y - dx1 * half_thickness_aa;
mrax = p1.x - dy1 * half_thickness_aa;
mray = p1.y + dx1 * half_thickness_aa;
}
}
// The two bevel vertices if the angle is right or obtuse
// miter_sign == 1, iff the outer (maybe bevelled) edge is on the right, -1 iff it is on the left
int miter_sign = (miter_l_recip >= 0) - (miter_l_recip < 0);
if (bevel)
{
// FIXME-OPT: benchmark if doing these computations only once in AA case saves cycles
b1x = p1.x + (dx1 - dy1 * miter_sign) * half_thickness;
b1y = p1.y + (dy1 + dx1 * miter_sign) * half_thickness;
b2x = p1.x + (dx2 + dy2 * miter_sign) * half_thickness;
b2y = p1.y + (dy2 - dx2 * miter_sign) * half_thickness;
if (antialias)
{
b1ax = p1.x + (dx1 - dy1 * miter_sign) * half_thickness_aa;
b1ay = p1.y + (dy1 + dx1 * miter_sign) * half_thickness_aa;
b2ax = p1.x + (dx2 + dy2 * miter_sign) * half_thickness_aa;
b2ay = p1.y + (dy2 - dx2 * miter_sign) * half_thickness_aa;
}
}
// Set the previous line direction so it doesn't need to be recomputed
dx1 = -dx2;
dy1 = -dy2;
sqlen1 = sqlen2;
// Now that we have all the point coordinates, put them into buffers
// Vertices for each point are ordered in vertex buffer like this (looking in the direction of the polyline):
// - left vertex*
// - right vertex*
// - left vertex AA fringe* (if antialias)
// - right vertex AA fringe* (if antialias)
// - the remaining vertex (if bevel)
// - the remaining vertex AA fringe (if bevel and antialias)
// (*) if there is bevel, these vertices are the ones on the incoming edge.
// Having all the vertices of the incoming edge in predictable positions is important - we reference them
// even if we don't know relevant line properties yet
const int vertex_count = antialias ? (bevel ? 6 : 4) : (bevel ? 3 : 2); // FIXME: shorten the expression
const unsigned int bi = antialias ? 4 : 2; // Outgoing edge bevel vertex index
const bool bevel_l = bevel && miter_sign < 0;
const bool bevel_r = bevel && miter_sign > 0;
_VtxWritePtr[0].pos.x = bevel_l ? b1x : mlx; _VtxWritePtr[0].pos.y = bevel_l ? b1y : mly; _VtxWritePtr[0].uv = opaque_uv; _VtxWritePtr[0].col = col;
_VtxWritePtr[1].pos.x = bevel_r ? b1x : mrx; _VtxWritePtr[1].pos.y = bevel_r ? b1y : mry; _VtxWritePtr[1].uv = opaque_uv; _VtxWritePtr[1].col = col;
if (bevel)
{
_VtxWritePtr[bi].pos.x = b2x; _VtxWritePtr[bi].pos.y = b2y; _VtxWritePtr[bi].uv = opaque_uv; _VtxWritePtr[bi].col = col;
}
if (antialias)
{
_VtxWritePtr[2].pos.x = bevel_l ? b1ax : mlax; _VtxWritePtr[2].pos.y = bevel_l ? b1ay : mlay; _VtxWritePtr[2].uv = opaque_uv; _VtxWritePtr[2].col = col_trans;
_VtxWritePtr[3].pos.x = bevel_r ? b1ax : mrax; _VtxWritePtr[3].pos.y = bevel_r ? b1ay : mray; _VtxWritePtr[3].uv = opaque_uv; _VtxWritePtr[3].col = col_trans;
if (bevel)
{
_VtxWritePtr[5].pos.x = b2ax; _VtxWritePtr[5].pos.y = b2ay; _VtxWritePtr[5].uv = opaque_uv; _VtxWritePtr[5].col = col_trans;
}
}
_VtxWritePtr += vertex_count;
if (i1 < count)
{
const int vtx_next_id = i1 < points_count - 1 ? _VtxCurrentIdx + vertex_count : first_vtx_idx;
unsigned int l1i = _VtxCurrentIdx + (bevel_l ? bi : 0);
unsigned int r1i = _VtxCurrentIdx + (bevel_r ? bi : 1);
unsigned int l2i = vtx_next_id;
unsigned int r2i = vtx_next_id + 1;
unsigned int ebi = _VtxCurrentIdx + (bevel_l ? 0 : 1); // incoming edge bevel vertex index
_IdxWritePtr[0] = (ImDrawIdx)l1i; _IdxWritePtr[1] = (ImDrawIdx)r1i; _IdxWritePtr[2] = (ImDrawIdx)r2i;
_IdxWritePtr[3] = (ImDrawIdx)l1i; _IdxWritePtr[4] = (ImDrawIdx)r2i; _IdxWritePtr[5] = (ImDrawIdx)l2i;
_IdxWritePtr += 6;
if (bevel)
{
_IdxWritePtr[0] = (ImDrawIdx)l1i; _IdxWritePtr[1] = (ImDrawIdx)r1i; _IdxWritePtr[2] = (ImDrawIdx)ebi;
_IdxWritePtr += 3;
}
if (antialias)
{
unsigned int l1ai = _VtxCurrentIdx + (bevel_l ? 5 : 2);
unsigned int r1ai = _VtxCurrentIdx + (bevel_r ? 5 : 3);
unsigned int l2ai = vtx_next_id + 2;
unsigned int r2ai = vtx_next_id + 3;
_IdxWritePtr[0] = (ImDrawIdx)l1ai; _IdxWritePtr[1] = (ImDrawIdx)l1i; _IdxWritePtr[2] = (ImDrawIdx)l2i;
_IdxWritePtr[3] = (ImDrawIdx)l1ai; _IdxWritePtr[4] = (ImDrawIdx)l2i; _IdxWritePtr[5] = (ImDrawIdx)l2ai;
_IdxWritePtr[6] = (ImDrawIdx)r1ai; _IdxWritePtr[7] = (ImDrawIdx)r1i; _IdxWritePtr[8] = (ImDrawIdx)r2i;
_IdxWritePtr[9] = (ImDrawIdx)r1ai; _IdxWritePtr[10] = (ImDrawIdx)r2i; _IdxWritePtr[11] = (ImDrawIdx)r2ai;
_IdxWritePtr += 12;
if (bevel)
{
_IdxWritePtr[0] = (ImDrawIdx)(_VtxCurrentIdx + (bevel_r ? 1 : 2));
_IdxWritePtr[1] = (ImDrawIdx)(_VtxCurrentIdx + (bevel_r ? 3 : 0));
_IdxWritePtr[2] = (ImDrawIdx)(_VtxCurrentIdx + (bevel_r ? 5 : 4));
_IdxWritePtr[3] = (ImDrawIdx)(_VtxCurrentIdx + (bevel_r ? 1 : 2));
_IdxWritePtr[4] = (ImDrawIdx)(_VtxCurrentIdx + (bevel_r ? 5 : 4));
_IdxWritePtr[5] = (ImDrawIdx)(_VtxCurrentIdx + (bevel_r ? 4 : 5));
_IdxWritePtr += 6;
}
}
}
_VtxCurrentIdx += vertex_count;
}
const int unused_indices = (int)(IdxBuffer.Data + IdxBuffer.Size - _IdxWritePtr);
const int unused_vertices = (int)(VtxBuffer.Size - _VtxCurrentIdx - _CmdHeader.VtxOffset);
if (unused_indices > 0 || unused_vertices > 0)
PrimUnreserve(unused_indices, unused_vertices);
}
}
else
{
if (Flags & ImDrawListFlags_AntiAliasedLines)
{
// Anti-aliased stroke
@ -972,6 +1230,7 @@ void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32
}
}
}
}
// We intentionally avoid using ImVec2 and its math operators here to reduce cost to a minimum for debug/non-inlined builds.
void ImDrawList::AddConvexPolyFilled(const ImVec2* points, const int points_count, ImU32 col)

View File

@ -469,17 +469,17 @@ IM_MSVC_RUNTIME_CHECKS_OFF
struct ImVec1
{
float x;
ImVec1() { x = 0.0f; }
ImVec1(float _x) { x = _x; }
constexpr ImVec1() : x(0.0f) { }
constexpr ImVec1(float _x) : x(_x) { }
};
// Helper: ImVec2ih (2D vector, half-size integer, for long-term packed storage)
struct ImVec2ih
{
short x, y;
ImVec2ih() { x = y = 0; }
ImVec2ih(short _x, short _y) { x = _x; y = _y; }
explicit ImVec2ih(const ImVec2& rhs) { x = (short)rhs.x; y = (short)rhs.y; }
constexpr ImVec2ih() : x(0), y(0) {}
constexpr ImVec2ih(short _x, short _y) : x(_x), y(_y) {}
constexpr explicit ImVec2ih(const ImVec2& rhs) : x((short)rhs.x), y((short)rhs.y) {}
};
// Helper: ImRect (2D axis aligned bounding-box)
@ -489,10 +489,10 @@ struct IMGUI_API ImRect
ImVec2 Min; // Upper-left
ImVec2 Max; // Lower-right
ImRect() : Min(0.0f, 0.0f), Max(0.0f, 0.0f) {}
ImRect(const ImVec2& min, const ImVec2& max) : Min(min), Max(max) {}
ImRect(const ImVec4& v) : Min(v.x, v.y), Max(v.z, v.w) {}
ImRect(float x1, float y1, float x2, float y2) : Min(x1, y1), Max(x2, y2) {}
constexpr ImRect() : Min(0.0f, 0.0f), Max(0.0f, 0.0f) {}
constexpr ImRect(const ImVec2& min, const ImVec2& max) : Min(min), Max(max) {}
constexpr ImRect(const ImVec4& v) : Min(v.x, v.y), Max(v.z, v.w) {}
constexpr ImRect(float x1, float y1, float x2, float y2) : Min(x1, y1), Max(x2, y2) {}
ImVec2 GetCenter() const { return ImVec2((Min.x + Max.x) * 0.5f, (Min.y + Max.y) * 0.5f); }
ImVec2 GetSize() const { return ImVec2(Max.x - Min.x, Max.y - Min.y); }
@ -1171,7 +1171,7 @@ enum ImGuiInputEventType
ImGuiInputEventType_MouseWheel,
ImGuiInputEventType_MouseButton,
ImGuiInputEventType_Key,
ImGuiInputEventType_Char,
ImGuiInputEventType_Text,
ImGuiInputEventType_Focus,
ImGuiInputEventType_COUNT
};

View File

@ -82,6 +82,7 @@ Index of this file:
#pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind
#pragma GCC diagnostic ignored "-Wformat-nonliteral" // warning: format not a string literal, format string not checked
#pragma GCC diagnostic ignored "-Wclass-memaccess" // [__GNUC__ >= 8] warning: 'memset/memcpy' clearing/writing an object of type 'xxxx' with no trivial copy-assignment; use assignment or value-initialization instead
#pragma GCC diagnostic ignored "-Wdeprecated-enum-enum-conversion" // warning: bitwise operation between different enumeration types ('XXXFlags_' and 'XXXFlagsPrivate_') is deprecated
#endif
//-------------------------------------------------------------------------