mirror of
https://github.com/Drezil/imgui.git
synced 2024-11-22 20:07:01 +00:00
Shadows: Added ImDrawShadowFlags, simplified API surface, reordered parameters
+ fix minor warnings + removed NGon variant for now.
This commit is contained in:
parent
cc7387f680
commit
50abd45040
@ -5816,8 +5816,9 @@ void ImGui::RenderWindowShadow(ImGuiWindow* window)
|
|||||||
ImGuiContext& g = *GImGui;
|
ImGuiContext& g = *GImGui;
|
||||||
ImGuiStyle& style = g.Style;
|
ImGuiStyle& style = g.Style;
|
||||||
float shadow_size = style.WindowShadowSize;
|
float shadow_size = style.WindowShadowSize;
|
||||||
|
ImU32 shadow_col = GetColorU32(ImGuiCol_WindowShadow);
|
||||||
ImVec2 shadow_offset = ImVec2(ImCos(style.WindowShadowOffsetAngle), ImSin(style.WindowShadowOffsetAngle)) * style.WindowShadowOffsetDist;
|
ImVec2 shadow_offset = ImVec2(ImCos(style.WindowShadowOffsetAngle), ImSin(style.WindowShadowOffsetAngle)) * style.WindowShadowOffsetDist;
|
||||||
window->DrawList->AddShadowRect(window->Pos, window->Pos + window->Size, shadow_size, shadow_offset, GetColorU32(ImGuiCol_WindowShadow), window->WindowRounding);
|
window->DrawList->AddShadowRect(window->Pos, window->Pos + window->Size, shadow_col, shadow_size, shadow_offset, ImDrawShadowFlags_CutOutShapeBackground, window->WindowRounding);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render title text, collapse button, close button
|
// Render title text, collapse button, close button
|
||||||
|
30
imgui.h
30
imgui.h
@ -179,6 +179,7 @@ typedef int ImGuiStyleVar; // -> enum ImGuiStyleVar_ // Enum: A
|
|||||||
typedef int ImGuiTableBgTarget; // -> enum ImGuiTableBgTarget_ // Enum: A color target for TableSetBgColor()
|
typedef int ImGuiTableBgTarget; // -> enum ImGuiTableBgTarget_ // Enum: A color target for TableSetBgColor()
|
||||||
typedef int ImDrawFlags; // -> enum ImDrawFlags_ // Flags: for ImDrawList functions
|
typedef int ImDrawFlags; // -> enum ImDrawFlags_ // Flags: for ImDrawList functions
|
||||||
typedef int ImDrawListFlags; // -> enum ImDrawListFlags_ // Flags: for ImDrawList instance
|
typedef int ImDrawListFlags; // -> enum ImDrawListFlags_ // Flags: for ImDrawList instance
|
||||||
|
typedef int ImDrawShadowFlags; // -> enum ImDrawShadowFlags_ // Flags: for ImDrawList::AddShadowRect(), AddShadowCircle() etc.
|
||||||
typedef int ImFontAtlasFlags; // -> enum ImFontAtlasFlags_ // Flags: for ImFontAtlas build
|
typedef int ImFontAtlasFlags; // -> enum ImFontAtlasFlags_ // Flags: for ImFontAtlas build
|
||||||
typedef int ImGuiBackendFlags; // -> enum ImGuiBackendFlags_ // Flags: for io.BackendFlags
|
typedef int ImGuiBackendFlags; // -> enum ImGuiBackendFlags_ // Flags: for io.BackendFlags
|
||||||
typedef int ImGuiButtonFlags; // -> enum ImGuiButtonFlags_ // Flags: for InvisibleButton()
|
typedef int ImGuiButtonFlags; // -> enum ImGuiButtonFlags_ // Flags: for InvisibleButton()
|
||||||
@ -2480,6 +2481,13 @@ enum ImDrawFlags_
|
|||||||
ImDrawFlags_RoundCornersMask_ = ImDrawFlags_RoundCornersAll | ImDrawFlags_RoundCornersNone
|
ImDrawFlags_RoundCornersMask_ = ImDrawFlags_RoundCornersAll | ImDrawFlags_RoundCornersNone
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Flags for ImDrawList::AddShadowRect(), AddShadowCircle() etc.
|
||||||
|
enum ImDrawShadowFlags_
|
||||||
|
{
|
||||||
|
ImDrawShadowFlags_None = 0,
|
||||||
|
ImDrawShadowFlags_CutOutShapeBackground = 1 << 0 // Do not render the shadow shape under the objects to be shadowed to save on fill-rate or facilitate blending. Slower on CPU.
|
||||||
|
};
|
||||||
|
|
||||||
// Flags for ImDrawList instance. Those are set automatically by ImGui:: functions from ImGuiIO settings, and generally not manipulated directly.
|
// Flags for ImDrawList instance. Those are set automatically by ImGui:: functions from ImGuiIO settings, and generally not manipulated directly.
|
||||||
// It is however possible to temporarily alter flags between calls to ImDrawList:: functions.
|
// It is however possible to temporarily alter flags between calls to ImDrawList:: functions.
|
||||||
enum ImDrawListFlags_
|
enum ImDrawListFlags_
|
||||||
@ -2568,17 +2576,19 @@ struct ImDrawList
|
|||||||
|
|
||||||
// Shadows primitives
|
// Shadows primitives
|
||||||
// [BETA] API
|
// [BETA] API
|
||||||
// - Add a shadow for a rectangular object, with min-max giving the object extents, and offset shifting the shadow. Rounding parameters refer to the object itself, not the shadow.
|
// - Add shadow for a object, with min/max or center/radius describing the object extents, and offset shifting the shadow.
|
||||||
// - The filled parameter causes the shadow "under" the object to be drawn as well. In the vast majority of cases, filled shadows are unnecessary and wasteful. We still provide the primitives for consistency and flexibility.
|
// - Rounding parameters refer to the object itself, not the shadow!
|
||||||
|
// - By default, the area under the object is filled, because this is simpler to process.
|
||||||
|
// Using the ImDrawShadowFlags_CutOutShapeBackground flag makes the function not render this area and leave a hole under the object.
|
||||||
|
// - Shadows w/ fill under the object: a bit faster for CPU, more pixels rendered, visible/darkening if used behind a transparent shape.
|
||||||
|
// Typically used by: small, frequent objects, opaque objects, transparent objects if shadow darkening isn't an issue.
|
||||||
|
// - Shadows w/ hole under the object: a bit slower for CPU, less pixels rendered, no difference if used behind a transparent shape.
|
||||||
|
// Typically used by: large, infrequent objects, transparent objects if exact blending/color matter.
|
||||||
|
// - FIXME-SHADOWS: 'offset' + ImDrawShadowFlags_CutOutBackground are not currently supported together with AddShadowCircle(), AddShadowConvexPoly().
|
||||||
#define IMGUI_HAS_SHADOWS 1
|
#define IMGUI_HAS_SHADOWS 1
|
||||||
IMGUI_API void AddShadowRect(const ImVec2& p_min, const ImVec2& p_max, float shadow_thickness, const ImVec2& offset, ImU32 col, float rounding = 0.0f, ImDrawCornerFlags rounding_corners = ImDrawCornerFlags_All);
|
IMGUI_API void AddShadowRect(const ImVec2& obj_min, const ImVec2& obj_max, ImU32 shadow_col, float shadow_thickness, const ImVec2& shadow_offset, ImDrawShadowFlags shadow_flags = 0, float obj_rounding = 0.0f, ImDrawCornerFlags obj_rounding_corners = ImDrawCornerFlags_All);
|
||||||
IMGUI_API void AddShadowRectFilled(const ImVec2& p_min, const ImVec2& p_max, float shadow_thickness, const ImVec2& offset, ImU32 col);
|
IMGUI_API void AddShadowCircle(const ImVec2& obj_center, float obj_radius, ImU32 shadow_col, float shadow_thickness, const ImVec2& shadow_offset, ImDrawShadowFlags shadow_flags = 0, int obj_num_segments = 12);
|
||||||
IMGUI_API void AddShadowCircle(const ImVec2& center, float radius, float shadow_thickness, const ImVec2& offset, ImU32 col, int num_segments = 12); // Offset not currently supported
|
IMGUI_API void AddShadowConvexPoly(const ImVec2* points, int points_count, ImU32 shadow_col, float shadow_thickness, const ImVec2& shadow_offset, ImDrawShadowFlags shadow_flags = 0);
|
||||||
IMGUI_API void AddShadowCircleFilled(const ImVec2& center, float radius, float shadow_thickness, const ImVec2& offset, ImU32 col, int num_segments = 12); // Offset not currently supported
|
|
||||||
IMGUI_API void AddShadowNGon(const ImVec2& center, float radius, float shadow_thickness, const ImVec2& offset, ImU32 col, int num_segments); // Offset not currently supported
|
|
||||||
IMGUI_API void AddShadowNGonFilled(const ImVec2& center, float radius, float shadow_thickness, const ImVec2& offset, ImU32 col, int num_segments); // Offset not currently supported
|
|
||||||
IMGUI_API void AddShadowConvexPoly(const ImVec2* points, int num_points, float shadow_thickness, const ImVec2& offset, ImU32 col); // Offset not currently supported
|
|
||||||
IMGUI_API void AddShadowConvexPolyFilled(const ImVec2* points, int num_points, float shadow_thickness, const ImVec2& offset, ImU32 col); // Offset not currently supported
|
|
||||||
|
|
||||||
// Stateful path API, add points then finish with PathFillConvex() or PathStroke()
|
// Stateful path API, add points then finish with PathFillConvex() or PathStroke()
|
||||||
inline void PathClear() { _Path.Size = 0; }
|
inline void PathClear() { _Path.Size = 0; }
|
||||||
|
@ -7659,17 +7659,17 @@ static void ShowExampleAppCustomRendering(bool* p_open)
|
|||||||
// Rectangle
|
// Rectangle
|
||||||
{
|
{
|
||||||
ImVec2 p = ImGui::GetCursorScreenPos();
|
ImVec2 p = ImGui::GetCursorScreenPos();
|
||||||
|
ImGui::Dummy(ImVec2(200.0f, 200.0f));
|
||||||
|
|
||||||
ImVec2 r1(p.x + 50.0f, p.y + 50.0f);
|
ImVec2 r1(p.x + 50.0f, p.y + 50.0f);
|
||||||
ImVec2 r2(p.x + 150.0f, p.y + 150.0f);
|
ImVec2 r2(p.x + 150.0f, p.y + 150.0f);
|
||||||
if (shadow_filled)
|
ImDrawShadowFlags shadow_flags = shadow_filled ? ImDrawShadowFlags_None : ImDrawShadowFlags_CutOutShapeBackground;
|
||||||
draw_list->AddShadowRectFilled(r1, r2, shadow_thickness, shadow_offset, ImGui::GetColorU32(shadow_color));
|
draw_list->AddShadowRect(r1, r2, ImGui::GetColorU32(shadow_color), shadow_thickness, shadow_offset, shadow_flags, shape_rounding);
|
||||||
else
|
|
||||||
draw_list->AddShadowRect(r1, r2, shadow_thickness, shadow_offset, ImGui::GetColorU32(shadow_color), shape_rounding);
|
|
||||||
if (wireframe)
|
if (wireframe)
|
||||||
draw_list->AddRect(r1, r2, ImGui::GetColorU32(shape_color), shape_rounding);
|
draw_list->AddRect(r1, r2, ImGui::GetColorU32(shape_color), shape_rounding);
|
||||||
else
|
else
|
||||||
draw_list->AddRectFilled(r1, r2, ImGui::GetColorU32(shape_color), shape_rounding);
|
draw_list->AddRectFilled(r1, r2, ImGui::GetColorU32(shape_color), shape_rounding);
|
||||||
ImGui::Dummy(ImVec2(200.0f, 200.0f));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
@ -7677,19 +7677,20 @@ static void ShowExampleAppCustomRendering(bool* p_open)
|
|||||||
// Circle
|
// Circle
|
||||||
{
|
{
|
||||||
ImVec2 p = ImGui::GetCursorScreenPos();
|
ImVec2 p = ImGui::GetCursorScreenPos();
|
||||||
|
ImGui::Dummy(ImVec2(200.0f, 200.0f));
|
||||||
|
|
||||||
|
// FIXME-SHADOWS: Offset forced to zero when shadow is not filled because it isn't supported
|
||||||
float off = 10.0f;
|
float off = 10.0f;
|
||||||
ImVec2 r1(p.x + 50.0f + off, p.y + 50.0f + off);
|
ImVec2 r1(p.x + 50.0f + off, p.y + 50.0f + off);
|
||||||
ImVec2 r2(p.x + 150.0f - off, p.y + 150.0f - off);
|
ImVec2 r2(p.x + 150.0f - off, p.y + 150.0f - off);
|
||||||
ImVec2 c(p.x + 100.0f, p.y + 100.0f);
|
ImVec2 center(p.x + 100.0f, p.y + 100.0f);
|
||||||
if (shadow_filled)
|
ImDrawShadowFlags shadow_flags = shadow_filled ? ImDrawShadowFlags_None : ImDrawShadowFlags_CutOutShapeBackground;
|
||||||
draw_list->AddShadowCircleFilled(c, 50.0f, shadow_thickness, shadow_offset, ImGui::GetColorU32(shadow_color));
|
draw_list->AddShadowCircle(center, 50.0f, ImGui::GetColorU32(shadow_color), shadow_thickness, shadow_filled ? shadow_offset : ImVec2(0.0f, 0.0f), shadow_flags, 0);
|
||||||
else
|
|
||||||
draw_list->AddShadowCircle(c, 50.0f, shadow_thickness, ImVec2(0.0f, 0.0f), ImGui::GetColorU32(shadow_color)); // Offset forced to zero here because it isn't supported
|
|
||||||
if (wireframe)
|
if (wireframe)
|
||||||
draw_list->AddCircle(c, 50.0f, ImGui::GetColorU32(shape_color), 0);
|
draw_list->AddCircle(center, 50.0f, ImGui::GetColorU32(shape_color), 0);
|
||||||
else
|
else
|
||||||
draw_list->AddCircleFilled(c, 50.0f, ImGui::GetColorU32(shape_color), 0);
|
draw_list->AddCircleFilled(center, 50.0f, ImGui::GetColorU32(shape_color), 0);
|
||||||
ImGui::Dummy(ImVec2(200.0f, 200.0f));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
@ -7697,6 +7698,7 @@ static void ShowExampleAppCustomRendering(bool* p_open)
|
|||||||
// Convex shape
|
// Convex shape
|
||||||
{
|
{
|
||||||
ImVec2 pos = ImGui::GetCursorScreenPos();
|
ImVec2 pos = ImGui::GetCursorScreenPos();
|
||||||
|
ImGui::Dummy(ImVec2(200.0f, 200.0f));
|
||||||
|
|
||||||
const ImVec2 poly_centre(pos.x + 50.0f, pos.y + 100.0f);
|
const ImVec2 poly_centre(pos.x + 50.0f, pos.y + 100.0f);
|
||||||
ImVec2* poly_points;
|
ImVec2* poly_points;
|
||||||
@ -7777,17 +7779,14 @@ static void ShowExampleAppCustomRendering(bool* p_open)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shadow_filled)
|
// FIXME-SHADOWS: Offset forced to zero when shadow is not filled because it isn't supported
|
||||||
draw_list->AddShadowConvexPolyFilled(poly_points, num_poly_points, shadow_thickness, shadow_offset, ImGui::GetColorU32(shadow_color));
|
ImDrawShadowFlags shadow_flags = shadow_filled ? ImDrawShadowFlags_None : ImDrawShadowFlags_CutOutShapeBackground;
|
||||||
else
|
draw_list->AddShadowConvexPoly(poly_points, num_poly_points, ImGui::GetColorU32(shadow_color), shadow_thickness, shadow_filled ? shadow_offset : ImVec2(0.0f, 0.0f), shadow_flags);
|
||||||
draw_list->AddShadowConvexPoly(poly_points, num_poly_points, shadow_thickness, ImVec2(0.0f, 0.0f), ImGui::GetColorU32(shadow_color)); // Offset forced to zero because it isn't supported
|
|
||||||
|
|
||||||
if (wireframe)
|
if (wireframe)
|
||||||
draw_list->AddPolyline(poly_points, num_poly_points, ImGui::GetColorU32(shape_color), true, 1.0f);
|
draw_list->AddPolyline(poly_points, num_poly_points, ImGui::GetColorU32(shape_color), true, 1.0f);
|
||||||
else
|
else
|
||||||
draw_list->AddConvexPolyFilled(poly_points, num_poly_points, ImGui::GetColorU32(shape_color));
|
draw_list->AddConvexPolyFilled(poly_points, num_poly_points, ImGui::GetColorU32(shape_color));
|
||||||
|
|
||||||
ImGui::Dummy(ImVec2(200.0f, 200.0f));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
draw_list->Flags = old_flags;
|
draw_list->Flags = old_flags;
|
||||||
|
198
imgui_draw.cpp
198
imgui_draw.cpp
@ -2095,25 +2095,29 @@ static void AddSubtractedRect(ImDrawList* draw_list, const ImVec2& a_min, const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void AddShadowRectEx(ImDrawList* draw_list, const ImVec2& p_min, const ImVec2& p_max, float shadow_thickness, const ImVec2& offset, ImU32 col, float rounding, ImDrawCornerFlags rounding_corners, bool is_filled)
|
void ImDrawList::AddShadowRect(const ImVec2& obj_min, const ImVec2& obj_max, ImU32 shadow_col, float shadow_thickness, const ImVec2& shadow_offset, ImDrawShadowFlags shadow_flags, float obj_rounding, ImDrawCornerFlags obj_rounding_corners)
|
||||||
{
|
{
|
||||||
|
if ((shadow_col & IM_COL32_A_MASK) == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
ImVec2* inner_rect_points = NULL; // Points that make up the shape of the inner rectangle (used when it has rounded corners)
|
ImVec2* inner_rect_points = NULL; // Points that make up the shape of the inner rectangle (used when it has rounded corners)
|
||||||
int inner_rect_points_count = 0;
|
int inner_rect_points_count = 0;
|
||||||
|
|
||||||
// Generate a path describing the inner rectangle and copy it to our buffer
|
// Generate a path describing the inner rectangle and copy it to our buffer
|
||||||
const bool is_rounded = (rounding > 0.0f) && (rounding_corners != ImDrawCornerFlags_None); // Do we have rounded corners?
|
const bool is_filled = (shadow_flags & ImDrawShadowFlags_CutOutShapeBackground) == 0;
|
||||||
|
const bool is_rounded = (obj_rounding > 0.0f) && (obj_rounding_corners != ImDrawCornerFlags_None); // Do we have rounded corners?
|
||||||
if (is_rounded && !is_filled)
|
if (is_rounded && !is_filled)
|
||||||
{
|
{
|
||||||
IM_ASSERT(draw_list->_Path.Size == 0);
|
IM_ASSERT(_Path.Size == 0);
|
||||||
draw_list->PathRect(p_min, p_max, rounding, rounding_corners);
|
PathRect(obj_min, obj_max, obj_rounding, obj_rounding_corners);
|
||||||
inner_rect_points_count = draw_list->_Path.Size;
|
inner_rect_points_count = _Path.Size;
|
||||||
inner_rect_points = (ImVec2*)alloca(inner_rect_points_count * sizeof(ImVec2)); //-V630
|
inner_rect_points = (ImVec2*)alloca(inner_rect_points_count * sizeof(ImVec2)); //-V630
|
||||||
memcpy(inner_rect_points, draw_list->_Path.Data, inner_rect_points_count * sizeof(ImVec2));
|
memcpy(inner_rect_points, _Path.Data, inner_rect_points_count * sizeof(ImVec2));
|
||||||
draw_list->_Path.Size = 0;
|
_Path.Size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_filled)
|
if (is_filled)
|
||||||
draw_list->PrimReserve(6 * 9, 4 * 9); // Reserve space for adding unclipped chunks
|
PrimReserve(6 * 9, 4 * 9); // Reserve space for adding unclipped chunks
|
||||||
|
|
||||||
// Draw the relevant chunks of the texture (the texture is split into a 3x3 grid)
|
// Draw the relevant chunks of the texture (the texture is split into a 3x3 grid)
|
||||||
for (int x = 0; x < 3; x++)
|
for (int x = 0; x < 3; x++)
|
||||||
@ -2121,67 +2125,52 @@ static void AddShadowRectEx(ImDrawList* draw_list, const ImVec2& p_min, const Im
|
|||||||
for (int y = 0; y < 3; y++)
|
for (int y = 0; y < 3; y++)
|
||||||
{
|
{
|
||||||
const int uv_index = x + (y + y + y); // y*3 formatted so as to ensure the compiler avoids an actual multiply
|
const int uv_index = x + (y + y + y); // y*3 formatted so as to ensure the compiler avoids an actual multiply
|
||||||
const ImVec4 uvs = draw_list->_Data->ShadowRectUvs[uv_index];
|
const ImVec4 uvs = _Data->ShadowRectUvs[uv_index];
|
||||||
|
|
||||||
ImVec2 draw_min, draw_max;
|
ImVec2 draw_min, draw_max;
|
||||||
switch (x)
|
switch (x)
|
||||||
{
|
{
|
||||||
case 0: draw_min.x = p_min.x - shadow_thickness; draw_max.x = p_min.x; break;
|
case 0: draw_min.x = obj_min.x - shadow_thickness; draw_max.x = obj_min.x; break;
|
||||||
case 1: draw_min.x = p_min.x; draw_max.x = p_max.x; break;
|
case 1: draw_min.x = obj_min.x; draw_max.x = obj_max.x; break;
|
||||||
case 2: draw_min.x = p_max.x; draw_max.x = p_max.x + shadow_thickness; break;
|
case 2: draw_min.x = obj_max.x; draw_max.x = obj_max.x + shadow_thickness; break;
|
||||||
}
|
}
|
||||||
switch (y)
|
switch (y)
|
||||||
{
|
{
|
||||||
case 0: draw_min.y = p_min.y - shadow_thickness; draw_max.y = p_min.y; break;
|
case 0: draw_min.y = obj_min.y - shadow_thickness; draw_max.y = obj_min.y; break;
|
||||||
case 1: draw_min.y = p_min.y; draw_max.y = p_max.y; break;
|
case 1: draw_min.y = obj_min.y; draw_max.y = obj_max.y; break;
|
||||||
case 2: draw_min.y = p_max.y; draw_max.y = p_max.y + shadow_thickness; break;
|
case 2: draw_min.y = obj_max.y; draw_max.y = obj_max.y + shadow_thickness; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ImVec2 uv_min(uvs.x, uvs.y);
|
ImVec2 uv_min(uvs.x, uvs.y);
|
||||||
ImVec2 uv_max(uvs.z, uvs.w);
|
ImVec2 uv_max(uvs.z, uvs.w);
|
||||||
if (is_filled)
|
if (is_filled)
|
||||||
draw_list->PrimRectUV(draw_min + offset, draw_max + offset, uv_min, uv_max, col); // No clipping path (draw entire shadow)
|
PrimRectUV(draw_min + shadow_offset, draw_max + shadow_offset, uv_min, uv_max, shadow_col); // No clipping path (draw entire shadow)
|
||||||
else if (is_rounded)
|
else if (is_rounded)
|
||||||
AddSubtractedRect(draw_list, draw_min + offset, draw_max + offset, uv_min, uv_max, inner_rect_points, inner_rect_points_count, col); // Complex path for rounded rectangles
|
AddSubtractedRect(this, draw_min + shadow_offset, draw_max + shadow_offset, uv_min, uv_max, inner_rect_points, inner_rect_points_count, shadow_col); // Complex path for rounded rectangles
|
||||||
else
|
else
|
||||||
AddSubtractedRect(draw_list, draw_min + offset, draw_max + offset, uv_min, uv_max, p_min, p_max, col); // Simple fast path for non-rounded rectangles
|
AddSubtractedRect(this, draw_min + shadow_offset, draw_max + shadow_offset, uv_min, uv_max, obj_min, obj_max, shadow_col); // Simple fast path for non-rounded rectangles
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImDrawList::AddShadowRectFilled(const ImVec2& p_min, const ImVec2& p_max, float shadow_thickness, const ImVec2& offset, ImU32 col)
|
|
||||||
{
|
|
||||||
if ((col & IM_COL32_A_MASK) == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
AddShadowRectEx(this, p_min, p_max, shadow_thickness, offset, col, 0.0f, ImDrawCornerFlags_None, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ImDrawList::AddShadowRect(const ImVec2& p_min, const ImVec2& p_max, float shadow_thickness, const ImVec2& offset, ImU32 col, float rounding, ImDrawCornerFlags rounding_corners)
|
|
||||||
{
|
|
||||||
if ((col & IM_COL32_A_MASK) == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
AddShadowRectEx(this, p_min, p_max, shadow_thickness, offset, col, rounding, rounding_corners, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add a shadow for a convex shape described by points and num_points
|
// Add a shadow for a convex shape described by points and num_points
|
||||||
static void AddShadowConvexShapeEx(ImDrawList* draw_list, const ImVec2* points, int num_points, float shadow_thickness, const ImVec2& offset, ImU32 col, bool is_filled)
|
void ImDrawList::AddShadowConvexPoly(const ImVec2* points, int points_count, ImU32 shadow_col, float shadow_thickness, const ImVec2& shadow_offset, ImDrawShadowFlags shadow_flags)
|
||||||
{
|
{
|
||||||
IM_ASSERT((is_filled || (ImLengthSqr(offset) < 0.00001f)) && "Drawing circle/convex shape shadows with no center fill and an offset is not currently supported");
|
const bool is_filled = (shadow_flags & ImDrawShadowFlags_CutOutShapeBackground) == 0;
|
||||||
IM_ASSERT(num_points >= 3);
|
IM_ASSERT((is_filled || (ImLengthSqr(shadow_offset) < 0.00001f)) && "Drawing circle/convex shape shadows with no center fill and an offset is not currently supported");
|
||||||
|
IM_ASSERT(points_count >= 3);
|
||||||
|
|
||||||
// Calculate poly vertex order
|
// Calculate poly vertex order
|
||||||
int vertex_winding = (((points[0].x * (points[1].y - points[2].y)) + (points[1].x * (points[2].y - points[0].y)) + (points[2].x * (points[0].y - points[1].y))) < 0.0f) ? -1 : 1;
|
int vertex_winding = (((points[0].x * (points[1].y - points[2].y)) + (points[1].x * (points[2].y - points[0].y)) + (points[2].x * (points[0].y - points[1].y))) < 0.0f) ? -1 : 1;
|
||||||
|
|
||||||
// If we're using anti-aliasing, then inset the shadow by 0.5 pixels to avoid unpleasant fringing artifacts
|
// If we're using anti-aliasing, then inset the shadow by 0.5 pixels to avoid unpleasant fringing artifacts
|
||||||
const bool use_inset_distance = (draw_list->Flags & ImDrawListFlags_AntiAliasedFill) && (!is_filled);
|
const bool use_inset_distance = (Flags & ImDrawListFlags_AntiAliasedFill) && (!is_filled);
|
||||||
const float inset_distance = 0.5f;
|
const float inset_distance = 0.5f;
|
||||||
|
|
||||||
const ImVec4 uvs = draw_list->_Data->ShadowRectUvs[9];
|
const ImVec4 uvs = _Data->ShadowRectUvs[9];
|
||||||
|
|
||||||
int tex_width = draw_list->_Data->Font->ContainerAtlas->TexWidth;
|
int tex_width = _Data->Font->ContainerAtlas->TexWidth;
|
||||||
int tex_height = draw_list->_Data->Font->ContainerAtlas->TexHeight;
|
int tex_height = _Data->Font->ContainerAtlas->TexHeight;
|
||||||
float inv_tex_width = 1.0f / (float)tex_width;
|
float inv_tex_width = 1.0f / (float)tex_width;
|
||||||
float inv_tex_height = 1.0f / (float)tex_height;
|
float inv_tex_height = 1.0f / (float)tex_height;
|
||||||
|
|
||||||
@ -2194,17 +2183,17 @@ static void AddShadowConvexShapeEx(ImDrawList* draw_list, const ImVec2* points,
|
|||||||
|
|
||||||
// Our basic algorithm here is that we generate a straight section along each edge, and then either one or two curved corner triangles at the corners,
|
// Our basic algorithm here is that we generate a straight section along each edge, and then either one or two curved corner triangles at the corners,
|
||||||
// which use an appropriate chunk of the texture to generate a smooth curve.
|
// which use an appropriate chunk of the texture to generate a smooth curve.
|
||||||
const int num_edges = num_points;
|
const int num_edges = points_count;
|
||||||
|
|
||||||
// Normalize a vector
|
// Normalize a vector
|
||||||
#define NORMALIZE(vec) ((vec) / ImLength((vec), 0.001f))
|
#define NORMALIZE(vec) ((vec) / ImLength((vec), 0.001f))
|
||||||
|
|
||||||
const int required_stack_mem = (num_edges * sizeof(ImVec2)) + (num_edges * sizeof(float));
|
const int required_stack_mem = (num_edges * sizeof(ImVec2)) + (num_edges * sizeof(float));
|
||||||
const ImU8* base_mem_for_normals_and_edges = (ImU8*)alloca(required_stack_mem);
|
ImU8* base_mem_for_normals_and_edges = (ImU8*)alloca(required_stack_mem);
|
||||||
ImU8* mem_for_normals_and_edges = (ImU8*)base_mem_for_normals_and_edges;
|
ImU8* mem_for_normals_and_edges = (ImU8*)base_mem_for_normals_and_edges;
|
||||||
|
|
||||||
// Calculate edge normals
|
// Calculate edge normals
|
||||||
ImVec2* edge_normals = (ImVec2*)mem_for_normals_and_edges;
|
ImVec2* edge_normals = (ImVec2*)(void*)mem_for_normals_and_edges;
|
||||||
mem_for_normals_and_edges += num_edges * sizeof(ImVec2);
|
mem_for_normals_and_edges += num_edges * sizeof(ImVec2);
|
||||||
|
|
||||||
for (int edge_index = 0; edge_index < num_edges; edge_index++)
|
for (int edge_index = 0; edge_index < num_edges; edge_index++)
|
||||||
@ -2218,7 +2207,7 @@ static void AddShadowConvexShapeEx(ImDrawList* draw_list, const ImVec2* points,
|
|||||||
|
|
||||||
// Pre-calculate edge scales
|
// Pre-calculate edge scales
|
||||||
// We need to do this because we need the edge strips to have widths that match up with the corner sections, otherwise pixel cracking can occur along the boundaries
|
// We need to do this because we need the edge strips to have widths that match up with the corner sections, otherwise pixel cracking can occur along the boundaries
|
||||||
float* edge_size_scales = (float*)mem_for_normals_and_edges;
|
float* edge_size_scales = (float*)(void*)mem_for_normals_and_edges;
|
||||||
mem_for_normals_and_edges += num_edges * sizeof(float);
|
mem_for_normals_and_edges += num_edges * sizeof(float);
|
||||||
IM_ASSERT_PARANOID(mem_for_normals_and_edges == (base_mem_for_normals_and_edges + required_stack_mem)); // Check we used exactly what we allocated
|
IM_ASSERT_PARANOID(mem_for_normals_and_edges == (base_mem_for_normals_and_edges + required_stack_mem)); // Check we used exactly what we allocated
|
||||||
|
|
||||||
@ -2251,21 +2240,21 @@ static void AddShadowConvexShapeEx(ImDrawList* draw_list, const ImVec2* points,
|
|||||||
|
|
||||||
const int max_vertices = (4 + (3 * 2) + (is_filled ? 1 : 0)) * num_edges; // 4 vertices per edge plus 3*2 for potentially two corner triangles, plus one per vertex for fill
|
const int max_vertices = (4 + (3 * 2) + (is_filled ? 1 : 0)) * num_edges; // 4 vertices per edge plus 3*2 for potentially two corner triangles, plus one per vertex for fill
|
||||||
const int max_indices = ((6 + (3 * 2)) * num_edges) + (is_filled ? ((num_edges - 2) * 3) : 0); // 2 tris per edge plus up to two corner triangles, plus fill triangles
|
const int max_indices = ((6 + (3 * 2)) * num_edges) + (is_filled ? ((num_edges - 2) * 3) : 0); // 2 tris per edge plus up to two corner triangles, plus fill triangles
|
||||||
draw_list->PrimReserve(max_indices, max_vertices);
|
PrimReserve(max_indices, max_vertices);
|
||||||
ImDrawIdx* idx_write = draw_list->_IdxWritePtr;
|
ImDrawIdx* idx_write = _IdxWritePtr;
|
||||||
ImDrawVert* vtx_write = draw_list->_VtxWritePtr;
|
ImDrawVert* vtx_write = _VtxWritePtr;
|
||||||
ImDrawIdx current_idx = (ImDrawIdx)draw_list->_VtxCurrentIdx;
|
ImDrawIdx current_idx = (ImDrawIdx)_VtxCurrentIdx;
|
||||||
|
|
||||||
ImVec2 previous_edge_start = points[0] + offset;
|
//ImVec2 previous_edge_start = points[0] + offset;
|
||||||
ImVec2 prev_edge_normal = edge_normals[num_edges - 1];
|
ImVec2 prev_edge_normal = edge_normals[num_edges - 1];
|
||||||
ImVec2 edge_start = points[0] + offset;
|
ImVec2 edge_start = points[0] + shadow_offset;
|
||||||
|
|
||||||
if (use_inset_distance)
|
if (use_inset_distance)
|
||||||
edge_start -= NORMALIZE(edge_normals[0] + prev_edge_normal) * inset_distance;
|
edge_start -= NORMALIZE(edge_normals[0] + prev_edge_normal) * inset_distance;
|
||||||
|
|
||||||
for (int edge_index = 0; edge_index < num_edges; edge_index++)
|
for (int edge_index = 0; edge_index < num_edges; edge_index++)
|
||||||
{
|
{
|
||||||
ImVec2 edge_end = points[(edge_index + 1) % num_edges] + offset;
|
ImVec2 edge_end = points[(edge_index + 1) % num_edges] + shadow_offset;
|
||||||
ImVec2 edge_normal = edge_normals[edge_index];
|
ImVec2 edge_normal = edge_normals[edge_index];
|
||||||
const float size_scale_start = edge_size_scales[edge_index];
|
const float size_scale_start = edge_size_scales[edge_index];
|
||||||
const float size_scale_end = edge_size_scales[(edge_index + 1) % num_edges];
|
const float size_scale_end = edge_size_scales[(edge_index + 1) % num_edges];
|
||||||
@ -2319,9 +2308,9 @@ static void AddShadowConvexShapeEx(ImDrawList* draw_list, const ImVec2* points,
|
|||||||
ImVec2 outer_edge_start = edge_start + (prev_edge_normal * expanded_thickness);
|
ImVec2 outer_edge_start = edge_start + (prev_edge_normal * expanded_thickness);
|
||||||
ImVec2 outer_edge_end = edge_start + (edge_normal * expanded_thickness);
|
ImVec2 outer_edge_end = edge_start + (edge_normal * expanded_thickness);
|
||||||
|
|
||||||
vtx_write->pos = edge_start; vtx_write->col = col; vtx_write->uv = solid_uv; vtx_write++;
|
vtx_write->pos = edge_start; vtx_write->col = shadow_col; vtx_write->uv = solid_uv; vtx_write++;
|
||||||
vtx_write->pos = outer_edge_end; vtx_write->col = col; vtx_write->uv = expanded_edge_uv; vtx_write++;
|
vtx_write->pos = outer_edge_end; vtx_write->col = shadow_col; vtx_write->uv = expanded_edge_uv; vtx_write++;
|
||||||
vtx_write->pos = outer_edge_start; vtx_write->col = col; vtx_write->uv = other_edge_uv; vtx_write++;
|
vtx_write->pos = outer_edge_start; vtx_write->col = shadow_col; vtx_write->uv = other_edge_uv; vtx_write++;
|
||||||
|
|
||||||
*(idx_write++) = current_idx;
|
*(idx_write++) = current_idx;
|
||||||
*(idx_write++) = current_idx + 1;
|
*(idx_write++) = current_idx + 1;
|
||||||
@ -2344,10 +2333,10 @@ static void AddShadowConvexShapeEx(ImDrawList* draw_list, const ImVec2* points,
|
|||||||
ImVec2 scaled_edge_uv_end = solid_uv + ((edge_uv - solid_uv) * size_scale_end);
|
ImVec2 scaled_edge_uv_end = solid_uv + ((edge_uv - solid_uv) * size_scale_end);
|
||||||
|
|
||||||
// Write vertices, inner first, then outer
|
// Write vertices, inner first, then outer
|
||||||
vtx_write->pos = edge_start; vtx_write->col = col; vtx_write->uv = solid_uv; vtx_write++;
|
vtx_write->pos = edge_start; vtx_write->col = shadow_col; vtx_write->uv = solid_uv; vtx_write++;
|
||||||
vtx_write->pos = edge_end; vtx_write->col = col; vtx_write->uv = solid_uv; vtx_write++;
|
vtx_write->pos = edge_end; vtx_write->col = shadow_col; vtx_write->uv = solid_uv; vtx_write++;
|
||||||
vtx_write->pos = outer_edge_end; vtx_write->col = col; vtx_write->uv = scaled_edge_uv_end; vtx_write++;
|
vtx_write->pos = outer_edge_end; vtx_write->col = shadow_col; vtx_write->uv = scaled_edge_uv_end; vtx_write++;
|
||||||
vtx_write->pos = outer_edge_start; vtx_write->col = col; vtx_write->uv = scaled_edge_uv_start; vtx_write++;
|
vtx_write->pos = outer_edge_start; vtx_write->col = shadow_col; vtx_write->uv = scaled_edge_uv_start; vtx_write++;
|
||||||
|
|
||||||
*(idx_write++) = current_idx;
|
*(idx_write++) = current_idx;
|
||||||
*(idx_write++) = current_idx + 1;
|
*(idx_write++) = current_idx + 1;
|
||||||
@ -2366,10 +2355,13 @@ static void AddShadowConvexShapeEx(ImDrawList* draw_list, const ImVec2* points,
|
|||||||
// Add vertices
|
// Add vertices
|
||||||
for (int edge_index = 0; edge_index < num_edges; edge_index++)
|
for (int edge_index = 0; edge_index < num_edges; edge_index++)
|
||||||
{
|
{
|
||||||
vtx_write->pos = points[edge_index] + offset; vtx_write->col = col; vtx_write->uv = solid_uv; vtx_write++;
|
vtx_write->pos = points[edge_index] + shadow_offset;
|
||||||
|
vtx_write->col = shadow_col;
|
||||||
|
vtx_write->uv = solid_uv;
|
||||||
|
vtx_write++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add tris
|
// Add triangles
|
||||||
for (int edge_index = 2; edge_index < num_edges; edge_index++)
|
for (int edge_index = 2; edge_index < num_edges; edge_index++)
|
||||||
{
|
{
|
||||||
*(idx_write++) = current_idx;
|
*(idx_write++) = current_idx;
|
||||||
@ -2381,28 +2373,28 @@ static void AddShadowConvexShapeEx(ImDrawList* draw_list, const ImVec2* points,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Release any unused vertices/indices
|
// Release any unused vertices/indices
|
||||||
int used_indices = (int)(idx_write - draw_list->_IdxWritePtr);
|
int used_indices = (int)(idx_write - _IdxWritePtr);
|
||||||
int used_vertices = (int)(vtx_write - draw_list->_VtxWritePtr);
|
int used_vertices = (int)(vtx_write - _VtxWritePtr);
|
||||||
draw_list->_IdxWritePtr = idx_write;
|
_IdxWritePtr = idx_write;
|
||||||
draw_list->_VtxWritePtr = vtx_write;
|
_VtxWritePtr = vtx_write;
|
||||||
draw_list->_VtxCurrentIdx = current_idx;
|
_VtxCurrentIdx = current_idx;
|
||||||
draw_list->PrimUnreserve(max_indices - used_indices, max_vertices - used_vertices);
|
PrimUnreserve(max_indices - used_indices, max_vertices - used_vertices);
|
||||||
#undef NORMALIZE
|
#undef NORMALIZE
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw a shadow for a circular object
|
// Draw a shadow for a circular object
|
||||||
// Uses the draw path and so wipes any existing data there
|
// Uses the draw path and so wipes any existing data there
|
||||||
static void AddShadowCircleEx(ImDrawList* draw_list, const ImVec2& center, float radius, float shadow_thickness, const ImVec2& offset, ImU32 col, int num_segments, bool is_filled)
|
void ImDrawList::AddShadowCircle(const ImVec2& obj_center, float obj_radius, ImU32 shadow_col, float shadow_thickness, const ImVec2& shadow_offset, ImDrawShadowFlags shadow_flags, int num_segments)
|
||||||
{
|
{
|
||||||
// Obtain segment count
|
// Obtain segment count
|
||||||
if (num_segments <= 0)
|
if (num_segments <= 0)
|
||||||
{
|
{
|
||||||
// Automatic segment count
|
// Automatic segment count
|
||||||
const int radius_idx = (int)radius - 1;
|
const int radius_idx = (int)obj_radius - 1;
|
||||||
if (radius_idx < IM_ARRAYSIZE(draw_list->_Data->CircleSegmentCounts))
|
if (radius_idx < IM_ARRAYSIZE(_Data->CircleSegmentCounts))
|
||||||
num_segments = draw_list->_Data->CircleSegmentCounts[radius_idx]; // Use cached value
|
num_segments = _Data->CircleSegmentCounts[radius_idx]; // Use cached value
|
||||||
else
|
else
|
||||||
num_segments = IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC(radius, draw_list->_Data->CircleSegmentMaxError);
|
num_segments = IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC(obj_radius, _Data->CircleSegmentMaxError);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -2411,68 +2403,16 @@ static void AddShadowCircleEx(ImDrawList* draw_list, const ImVec2& center, float
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Generate a path describing the inner circle and copy it to our buffer
|
// Generate a path describing the inner circle and copy it to our buffer
|
||||||
|
IM_ASSERT(_Path.Size == 0);
|
||||||
IM_ASSERT(draw_list->_Path.Size == 0);
|
|
||||||
|
|
||||||
const float a_max = (IM_PI * 2.0f) * ((float)num_segments - 1.0f) / (float)num_segments;
|
const float a_max = (IM_PI * 2.0f) * ((float)num_segments - 1.0f) / (float)num_segments;
|
||||||
if (num_segments == 12)
|
if (num_segments == 12)
|
||||||
draw_list->PathArcToFast(center, radius, 0, 11);
|
PathArcToFast(obj_center, obj_radius, 0, 12 - 1);
|
||||||
else
|
else
|
||||||
draw_list->PathArcTo(center, radius, 0.0f, a_max, num_segments - 1);
|
PathArcTo(obj_center, obj_radius, 0.0f, a_max, num_segments - 1);
|
||||||
|
|
||||||
// Draw the shadow using the convex shape code
|
// Draw the shadow using the convex shape code
|
||||||
AddShadowConvexShapeEx(draw_list, draw_list->_Path.Data, draw_list->_Path.Size, shadow_thickness, offset, col, is_filled);
|
AddShadowConvexPoly(_Path.Data, _Path.Size, shadow_col, shadow_thickness, shadow_offset, shadow_flags);
|
||||||
|
_Path.Size = 0;
|
||||||
// Clear the path we generated
|
|
||||||
draw_list->_Path.Size = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ImDrawList::AddShadowCircle(const ImVec2& center, float radius, float shadow_thickness, const ImVec2& offset, ImU32 col, int num_segments)
|
|
||||||
{
|
|
||||||
if (((col & IM_COL32_A_MASK) == 0) || (radius <= 0))
|
|
||||||
return;
|
|
||||||
|
|
||||||
AddShadowCircleEx(this, center, radius, shadow_thickness, offset, col, num_segments, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ImDrawList::AddShadowCircleFilled(const ImVec2& center, float radius, float shadow_thickness, const ImVec2& offset, ImU32 col, int num_segments)
|
|
||||||
{
|
|
||||||
if (((col & IM_COL32_A_MASK) == 0) || (radius <= 0))
|
|
||||||
return;
|
|
||||||
|
|
||||||
AddShadowCircleEx(this, center, radius, shadow_thickness, offset, col, num_segments, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ImDrawList::AddShadowNGon(const ImVec2& center, float radius, float shadow_thickness, const ImVec2& offset, ImU32 col, int num_segments)
|
|
||||||
{
|
|
||||||
if (((col & IM_COL32_A_MASK) == 0) || (radius <= 0))
|
|
||||||
return;
|
|
||||||
|
|
||||||
AddShadowCircleEx(this, center, radius, shadow_thickness, offset, col, num_segments, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ImDrawList::AddShadowNGonFilled(const ImVec2& center, float radius, float shadow_thickness, const ImVec2& offset, ImU32 col, int num_segments)
|
|
||||||
{
|
|
||||||
if (((col & IM_COL32_A_MASK) == 0) || (radius <= 0))
|
|
||||||
return;
|
|
||||||
|
|
||||||
AddShadowCircleEx(this, center, radius, shadow_thickness, offset, col, num_segments, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ImDrawList::AddShadowConvexPoly(const ImVec2* points, int num_points, float shadow_thickness, const ImVec2& offset, ImU32 col)
|
|
||||||
{
|
|
||||||
if ((col & IM_COL32_A_MASK) == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
AddShadowConvexShapeEx(this, points, num_points, shadow_thickness, offset, col, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ImDrawList::AddShadowConvexPolyFilled(const ImVec2* points, int num_points, float shadow_thickness, const ImVec2& offset, ImU32 col)
|
|
||||||
{
|
|
||||||
if ((col & IM_COL32_A_MASK) == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
AddShadowConvexShapeEx(this, points, num_points, shadow_thickness, offset, col, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
Loading…
Reference in New Issue
Block a user