Added Panel title

This commit is contained in:
OmniaX-Dev 2026-04-15 21:00:39 +02:00
parent e8d13b931e
commit 84c4c2eb88
10 changed files with 347 additions and 137 deletions

View file

@ -1,17 +1,17 @@
% ================== testTheme.txt ==================
% ---- Variables ----
$accentColor = Color(rgba(255, 0, 255, 255))
const $color2 = Color(#0000FFFF)
$accentColor = rgba(255, 0, 255, 255)
const $color2 = #0000FFFF
% -------------------
window.backgroundColor = Color(rgba(160, 160, 160, 255))
window.backgroundColor = rgba(160, 160, 160, 255)
$accentColor = Color(rgb(255, 0, 0))
$accentColor = rgb(255, 0, 0)
(label) {
textColor = $accentColor
backgroundColor = Color(#000000FF)
backgroundColor = #000000FF
borderColor = $accentColor
fontSize = 20
borderRadius = 0
@ -46,26 +46,30 @@ $accentColor = Color(rgb(255, 0, 0))
}
(checkbox:active) {
textColor = Color(#000050FF)
textColor = #000050FF
}
(panel) {
backgroundColor = Color(#AAAAAAFF)
borderColor = Color(#000000FF)
borderRadius = 8
borderWidth = 4
backgroundColor = #AAAAAAFF
borderColor = color_black
borderRadius = 10
borderWidth = 2
showBorder = true
showBackground = true
padding = Rect(15, 15, 15, 15)
showTitle = true
titleColor = Color(#000000FF)
titlebarType = "full"
titleHeight = 30
titleColor = #444444FF
titlebarColor = #999999FF
titlebarBorderColor = #909090FF
titlebarBorderWidth = 2
titlebarType = full
titlebarHeight = 18
titlebarFontSize = 18
titlebarTextAlign = text_left
}
(@testLabel label) {
textColor = $color2
backgroundColor = Color(#000000FF)
backgroundColor = #000000FF
fontSize = 50
}
@ -75,7 +79,7 @@ $accentColor = Color(rgb(255, 0, 0))
}
(@testLabel2 label:hover) {
borderColor = Color(#208080FF)
borderColor = #208080FF
}
(@testLabel2 label:pressed) {
@ -84,7 +88,7 @@ $accentColor = Color(rgb(255, 0, 0))
(label:hover) {
textColor = color_green
borderColor = Color(rgb(0, 255, 0))
borderColor = rgb(0, 255, 0)
}
(label:pressed) {
@ -97,19 +101,19 @@ $accentColor = Color(rgb(255, 0, 0))
(@testLabel label:pressed) {
backgroundColor = color_firebrick
textColor = Color(#505050FF)
textColor = #505050FF
}
(label:disabled) {
backgroundColor = Color(#EEEEEEFF)
%textColor = Color(#505050FF)
%borderColor = Color(#000000FF)
backgroundColor = #EEEEEEFF
%textColor = #505050FF
%borderColor = #000000FF
}
(@label3 label) {
textColor = $color2
backgroundColor = Color(#000000FF)
borderColor = Color(#FF0000FF)
backgroundColor = #000000FF
borderColor = #FF0000FF
borderWidth = 4
borderRadius = 15
}

View file

@ -16,10 +16,10 @@
***Implement wrappers in Renderer2D to take a center and size for rects
***find a way to add fixed update to gui::Window
***Add triangle drawing functions to BasicRenderer2D
***Implement Panel title
Add theme caching
Implement global scale (probably query desktop scale and adjust accordingly)
Implement show/hide functionality for widgets
Implement Panel title
Create reliable default stylesheet
Implement cursors in Stylesheet
@ -28,10 +28,10 @@ Implement cursors in Stylesheet
Implement following widgets:
***Label
***Checkbox
***Panel / Container
***Title Label
Button
Image/Icon
Panel / Container
Title Label
Radio Button
Grouping
Text Input

View file

@ -494,6 +494,10 @@ namespace ogfx
m_defaultStylesheetVariables["color_darkcyan"] = { "Color(" + Colors::DarkCyan.hexString(true, "#") + ")", true };
m_defaultStylesheetVariables["color_darkmagenta"] = { "Color(" + Colors::DarkMagenta.hexString(true, "#") + ")", true };
m_defaultStylesheetVariables["color_darkyellow"] = { "Color(" + Colors::DarkYellow.hexString(true, "#") + ")", true };
//Text Align
m_defaultStylesheetVariables["text_center"] = { String("").add(cast<i32>(eTextAlign::Center)), true };
m_defaultStylesheetVariables["text_left"] = { String("").add(cast<i32>(eTextAlign::Left)), true };
}

View file

@ -59,6 +59,11 @@ namespace ogfx
Count
};
public: enum class eTextAlign : u8 {
Default = 0,
Center,
Left
};
public:
inline WindowCore(void) { }
virtual ~WindowCore(void);

View file

@ -20,6 +20,7 @@
#include "Containers.hpp"
#include "../../render/BasicRenderer.hpp"
#include "../Window.hpp"
namespace ogfx
{
@ -46,15 +47,85 @@ namespace ogfx
enableBorder(getThemeValue<bool>(theme, "panel.showBorder", true));
enableBackground(getThemeValue<bool>(theme, "panel.showBackground", true));
setBorderColor(getThemeValue<Color>(theme, "panel.borderColor", Colors::Black));
m_titleColor = getThemeValue<Color>(theme, "panel.titleColor", Colors::Black);
m_showTitle = getThemeValue<bool>(theme, "panel.showTitle", false);
m_titleHeight = getThemeValue<f32>(theme, "panel.titleHeight", 30);
m_titleType = getThemeValue<String>(theme, "panel.titlebarType", TitleBarTypes::None);
setPadding(getThemeValue<Rectangle>(theme, "panel.padding", { 15, 15, 15, 15 }));
m_basePadding = getPadding();
m_titleColor = getThemeValue<Color>(theme, "panel.titleColor", Colors::Black);
m_titlebarColor = getThemeValue<Color>(theme, "panel.titlebarColor", Colors::Transparent);
m_titlebarBorderColor = getThemeValue<Color>(theme, "panel.titlebarBorderColor", Colors::Black);
m_titlebarHeight = getThemeValue<f32>(theme, "panel.titlebarHeight", 30);
m_titlebarBorderWidth = getThemeValue<i32>(theme, "panel.titlebarBorderWidth", 1);
m_titlebarFontSize = getThemeValue<i32>(theme, "panel.titlebarFontSize", 26);
m_titleTextAlign = getThemeValue<i32>(theme, "panel.titlebarTextAlign", cast<i32>(WindowCore::eTextAlign::Left));
setTitlebarType(getThemeValue<String>(theme, "panel.titlebarType", TitleBarTypes::None));
}
void Panel::onDraw(ogfx::BasicRenderer2D& gfx)
{
draw_titlebar(gfx);
}
void Panel::setTitlebarType(const String& type)
{
String t = type.new_toLower().trim();
if (t == TitleBarTypes::None)
{
setPadding(m_basePadding);
m_titlebarType = TitleBarTypes::NoneValue;
}
else if (t == TitleBarTypes::Minimal)
{
setPadding(m_basePadding + Rectangle { 0, m_titlebarHeight, 0, 0 });
m_titlebarType = TitleBarTypes::MinimalValue;
}
else if (t == TitleBarTypes::Full)
{
setPadding(m_basePadding + Rectangle { 0, m_titlebarHeight, 0, 0 });
m_titlebarType = TitleBarTypes::FullValue;
}
}
String Panel::getTitlebarType(void) const
{
switch (m_titlebarType)
{
case TitleBarTypes::FullValue: return TitleBarTypes::Full;
case TitleBarTypes::MinimalValue: return TitleBarTypes::Minimal;
case TitleBarTypes::NoneValue: return TitleBarTypes::None;
default: return TitleBarTypes::None;
}
}
void Panel::draw_titlebar(BasicRenderer2D& gfx)
{
f32 br = cast<f32>(getBorderWidth());
br /= 2;
Rectangle titleBarBounds {
getGlobalPosition() + Vec2 { br, br },
Vec2 { getw(), m_titlebarHeight } - Vec2 { br * 2, br * 2 }
};
switch (m_titlebarType)
{
case TitleBarTypes::FullValue:
{
gfx.outlinedRoundRect(titleBarBounds, m_titlebarColor, m_titlebarColor, { cast<f32>(getBorderRadius()), cast<f32>(getBorderRadius()), 0, 0 }, getBorderWidth());
gfx.drawLine({ getGlobalPosition() + Vec2 { 0, m_titlebarHeight - 2 }, getGlobalPosition() + Vec2 { getGlobalBounds().w, m_titlebarHeight - 2 } }, m_titlebarBorderColor, m_titlebarBorderWidth);
if (m_titleTextAlign == cast<i32>(WindowCore::eTextAlign::Center))
gfx.drawCenteredString(m_title, titleBarBounds, m_titleColor, m_titlebarFontSize);
else
gfx.drawString(m_title, titleBarBounds.getPosition() + Vec2 { 10, 5 }, m_titleColor, m_titlebarFontSize);
break;
}
case TitleBarTypes::MinimalValue:
{
if (m_titleTextAlign == cast<i32>(WindowCore::eTextAlign::Center))
gfx.drawCenteredString(m_title, titleBarBounds, m_titleColor, m_titlebarFontSize);
else
gfx.drawString(m_title, titleBarBounds.getPosition() + Vec2 { 10, 5 }, m_titleColor, m_titlebarFontSize);
break;
}
case TitleBarTypes::NoneValue:
default: break;
}
}
}
}

View file

@ -34,7 +34,11 @@ namespace ogfx
{
inline static const String None { "none" };
inline static const String Full { "full" };
inline static const String Minimal { "monimal" };
inline static const String Minimal { "minimal" };
inline static constexpr i32 NoneValue = 0;
inline static constexpr i32 FullValue = 1;
inline static constexpr i32 MinimalValue = 2;
};
public:
inline Panel(WindowCore& window) : Widget({ 0, 0, 0, 0 }, window) { create(); }
@ -42,15 +46,27 @@ namespace ogfx
void applyTheme(const ostd::Stylesheet& theme) override;
void onDraw(ogfx::BasicRenderer2D& gfx) override;
void setTitlebarType(const String& type);
String getTitlebarType(void) const;
inline void setBackGroundColor(const Color& color) { m_backgroundColor = color; }
inline Color getBackgroundColor(void) { return m_backgroundColor; }
inline String getTitlebarType(void) const { return m_titleType; }
inline String getTitle(void) const { return m_title; }
inline void setTitle(const String& title) { m_title = title; }
private:
Color m_titleColor { 0, 0, 0 };
bool m_showTitle { false };
String m_titleType = TitleBarTypes::None;
f32 m_titleHeight { 30 };
void draw_titlebar(BasicRenderer2D& gfx);
private:
String m_title { "Panel" };
Color m_titleColor { Colors::Black };
i32 m_titlebarType = TitleBarTypes::NoneValue;
f32 m_titlebarHeight { 30 };
i32 m_titlebarBorderWidth { 1 };
i32 m_titlebarFontSize { 26 };
Color m_titlebarColor { Colors::Transparent };
Color m_titlebarBorderColor { Colors::Black };
Rectangle m_basePadding { 0, 0, 0, 0 };
i32 m_titleTextAlign { 0 };
};
}
}

View file

@ -60,6 +60,7 @@ namespace ogfx
{
m_window = &window;
if (m_initialized) return set_error_state(tErrors::NoError);
SDL_SetRenderDrawBlendMode(m_window->getSDLRenderer(), SDL_BLENDMODE_BLEND);
init_arrays();
m_initialized = true;
loadDefaultFont(20);
@ -434,46 +435,52 @@ namespace ogfx
}
void BasicRenderer2D::drawRoundRect(const Rectangle& rect, const Color& color, f32 radius, i32 thickness)
{
drawRoundRect(rect, color, { radius, radius, radius, radius }, thickness);
}
void BasicRenderer2D::drawRoundRect(const Vec2& center, const Vec2& size, const Color& color, f32 radius, i32 thickness)
{
drawRoundRect({ center.x - size.x * 0.5f, center.y - size.y * 0.5f, size.x, size.y }, color, { radius, radius, radius, radius }, thickness);
}
void BasicRenderer2D::drawRoundRect(const Vec2& center, const Vec2& size, const Color& color, const Rectangle& radii, i32 thickness)
{
drawRoundRect({ center.x - size.x * 0.5f, center.y - size.y * 0.5f, size.x, size.y }, color, radii, thickness);
}
void BasicRenderer2D::drawRoundRect(const Rectangle& rect, const Color& color, const Rectangle& radii, i32 thickness)
{
if (!m_initialized || thickness <= 0)
return;
// Clamp radius so it never exceeds half the smallest dimension
radius = std::max(0.0f, std::min(radius, std::min(rect.w, rect.h) * 0.5f));
// radii: x=TL, y=TR, w=BR, h=BL
f32 maxR = std::min(rect.w, rect.h) * 0.5f;
f32 rTL = std::max(0.0f, std::min(radii.x, maxR));
f32 rTR = std::max(0.0f, std::min(radii.y, maxR));
f32 rBR = std::max(0.0f, std::min(radii.w, maxR));
f32 rBL = std::max(0.0f, std::min(radii.h, maxR));
f32 half = thickness * 0.5f;
// Inset rectangle so the border stays INSIDE the given bounds
f32 x1 = rect.x + half;
f32 y1 = rect.y + half;
f32 x2 = rect.x + rect.w - half;
f32 y2 = rect.y + rect.h - half;
// Corner centers
Vec2 TL { x1 + radius, y1 + radius };
Vec2 TR { x2 - radius, y1 + radius };
Vec2 BR { x2 - radius, y2 - radius };
Vec2 BL { x1 + radius, y2 - radius };
// Straight edges
drawLine({ {x1 + rTL, y1}, {x2 - rTR, y1} }, color, thickness, false); // top
drawLine({ {x2, y1 + rTR}, {x2, y2 - rBR} }, color, thickness, false); // right
drawLine({ {x2 - rBR, y2}, {x1 + rBL, y2} }, color, thickness, false); // bottom
drawLine({ {x1, y2 - rBL}, {x1, y1 + rTL} }, color, thickness, false); // left
// Straight edges (shortened to meet the arcs cleanly)
drawLine({ {x1 + radius, y1}, {x2 - radius, y1} }, color, thickness, false); // top
drawLine({ {x2, y1 + radius}, {x2, y2 - radius} }, color, thickness, false); // right
drawLine({ {x2 - radius, y2}, {x1 + radius, y2} }, color, thickness, false); // bottom
drawLine({ {x1, y2 - radius}, {x1, y1 + radius} }, color, thickness, false); // left
// Corner arcs
auto segments = [](f32 r) -> i32 { return std::max(6, i32(r * 0.75f)); };
// Number of segments for smooth arcs
i32 segments = std::max(6, i32(radius * 0.75f));
// Quarterellipse strokes (each is 90°)
generate_ellipse_stroke(TL, radius, radius, thickness, M_PI, M_PI + M_PI * 0.5f, color, segments); // TL
generate_ellipse_stroke(TR, radius, radius, thickness, 1.5f * M_PI, 2.0f * M_PI, color, segments); // TR
generate_ellipse_stroke(BR, radius, radius, thickness, 0.0f, M_PI * 0.5f, color, segments); // BR
generate_ellipse_stroke(BL, radius, radius, thickness, M_PI * 0.5f, M_PI, color, segments); // BL
}
void BasicRenderer2D::drawRoundRect(const Vec2& center, const Vec2& size, const Color& color, f32 radius, i32 thickness)
{
drawRoundRect({ center.x - size.x * 0.5f, center.y - size.y * 0.5f, size.x, size.y }, color, radius, thickness);
if (rTL > 0) generate_ellipse_stroke({ x1 + rTL, y1 + rTL }, rTL, rTL, thickness, M_PI, M_PI * 1.5f, color, segments(rTL));
if (rTR > 0) generate_ellipse_stroke({ x2 - rTR, y1 + rTR }, rTR, rTR, thickness, M_PI * 1.5f, M_PI * 2.0f, color, segments(rTR));
if (rBR > 0) generate_ellipse_stroke({ x2 - rBR, y2 - rBR }, rBR, rBR, thickness, 0.0f, M_PI * 0.5f, color, segments(rBR));
if (rBL > 0) generate_ellipse_stroke({ x1 + rBL, y2 - rBL }, rBL, rBL, thickness, M_PI * 0.5f, M_PI, color, segments(rBL));
}
void BasicRenderer2D::drawCircle(const Vec2& center, f32 radius, const Color& color, i32 thickness)
@ -500,7 +507,7 @@ namespace ogfx
void BasicRenderer2D::drawEllipse(const Rectangle& rect, const Color& color, i32 thickness)
{
if (!m_initialized || thickness <= 0)
if (!m_initialized || thickness <= 0)
return;
Vec2 center = { rect.x + rect.w*0.5f, rect.y + rect.h*0.5f };
@ -526,9 +533,9 @@ namespace ogfx
drawLine({ B, C }, color, thickness, false);
drawLine({ C, A }, color, thickness, false);
}
void BasicRenderer2D::fillRect(const Rectangle& rect, const Color& color)
{
@ -556,106 +563,172 @@ namespace ogfx
}
void BasicRenderer2D::fillRoundRect(const Rectangle& rect, const Color& color, f32 radius)
{
fillRoundRect(rect, color, { radius, radius, radius, radius });
}
void BasicRenderer2D::fillRoundRect(const Vec2& center, const Vec2& size, const Color& color, f32 radius)
{
fillRoundRect({ center.x - size.x * 0.5f, center.y - size.y * 0.5f, size.x, size.y }, color, { radius, radius, radius, radius });
}
void BasicRenderer2D::fillRoundRect(const Vec2& center, const Vec2& size, const Color& color, const Rectangle& radii)
{
fillRoundRect({ center.x - size.x * 0.5f, center.y - size.y * 0.5f, size.x, size.y }, color, radii);
}
void BasicRenderer2D::fillRoundRect(const Rectangle& rect, const Color& color, const Rectangle& radii)
{
if (!m_initialized)
return;
// Clamp radius
radius = std::max(0.0f, std::min(radius, std::min(rect.w, rect.h) * 0.5f));
f32 maxR = std::min(rect.w, rect.h) * 0.5f;
f32 rTL = std::max(0.0f, std::min(radii.x, maxR));
f32 rTR = std::max(0.0f, std::min(radii.y, maxR));
f32 rBR = std::max(0.0f, std::min(radii.w, maxR));
f32 rBL = std::max(0.0f, std::min(radii.h, maxR));
f32 x1 = rect.x;
f32 y1 = rect.y;
f32 x2 = rect.x + rect.w;
f32 y2 = rect.y + rect.h;
f32 cx1 = x1 + radius;
f32 cy1 = y1 + radius;
f32 cx2 = x2 - radius;
f32 cy2 = y2 - radius;
// The largest corner radius on each side determines the inset for that side
f32 topInset = std::max(rTL, rTR);
f32 bottomInset = std::max(rBL, rBR);
f32 leftInset = std::max(rTL, rBL);
f32 rightInset = std::max(rTR, rBR);
// Number of segments for smooth corners
i32 segments = std::max(6, i32(radius * 0.75f));
//
// 1. Fill the center rectangle
//
// Center rectangle
{
Vec2 verts[4] = {
{ cx1, cy1 },
{ cx2, cy1 },
{ cx2, cy2 },
{ cx1, cy2 }
{ x1 + leftInset, y1 + topInset },
{ x2 - rightInset, y1 + topInset },
{ x2 - rightInset, y2 - bottomInset },
{ x1 + leftInset, y2 - bottomInset }
};
u32 inds[6] = { 0,1,2, 2,3,0 };
u32 inds[6] = QUAD_INDICES_ARR;
push_polygon(verts, nullptr, 4, inds, 6, color, nullptr);
}
//
// 2. Fill the four side rectangles
//
// Top
if (radius > 0)
// Top strip
{
Vec2 verts[4] = {
{ x1 + radius, y1 },
{ x2 - radius, y1 },
{ x2 - radius, y1 + radius },
{ x1 + radius, y1 + radius }
{ x1 + rTL, y1 },
{ x2 - rTR, y1 },
{ x2 - rTR, y1 + topInset },
{ x1 + rTL, y1 + topInset }
};
u32 inds[6] = { 0,1,2, 2,3,0 };
u32 inds[6] = QUAD_INDICES_ARR;
push_polygon(verts, nullptr, 4, inds, 6, color, nullptr);
}
// Bottom
// Bottom strip
{
Vec2 verts[4] = {
{ x1 + radius, y2 - radius },
{ x2 - radius, y2 - radius },
{ x2 - radius, y2 },
{ x1 + radius, y2 }
{ x1 + rBL, y2 - bottomInset },
{ x2 - rBR, y2 - bottomInset },
{ x2 - rBR, y2 },
{ x1 + rBL, y2 }
};
u32 inds[6] = { 0,1,2, 2,3,0 };
u32 inds[6] = QUAD_INDICES_ARR;
push_polygon(verts, nullptr, 4, inds, 6, color, nullptr);
}
// Left
// Left strip
{
Vec2 verts[4] = {
{ x1, y1 + radius },
{ x1 + radius, y1 + radius },
{ x1 + radius, y2 - radius },
{ x1, y2 - radius }
{ x1, y1 + rTL },
{ x1 + leftInset, y1 + rTL },
{ x1 + leftInset, y2 - rBL },
{ x1, y2 - rBL }
};
u32 inds[6] = { 0,1,2, 2,3,0 };
u32 inds[6] = QUAD_INDICES_ARR;
push_polygon(verts, nullptr, 4, inds, 6, color, nullptr);
}
// Right
// Right strip
{
Vec2 verts[4] = {
{ x2 - radius, y1 + radius },
{ x2, y1 + radius },
{ x2, y2 - radius },
{ x2 - radius, y2 - radius }
{ x2 - rightInset, y1 + rTR },
{ x2, y1 + rTR },
{ x2, y2 - rBR },
{ x2 - rightInset, y2 - rBR }
};
u32 inds[6] = { 0,1,2, 2,3,0 };
u32 inds[6] = QUAD_INDICES_ARR;
push_polygon(verts, nullptr, 4, inds, 6, color, nullptr);
}
//
// 3. Fill the four rounded corners (quarter ellipses)
//
// Fill gaps between corners and strips when radii differ on the same side
// Top-left gap (if rTL < topInset, there's a rectangular gap below the TL corner)
if (rTL < topInset)
{
Vec2 verts[4] = {
{ x1, y1 + rTL },
{ x1 + leftInset, y1 + rTL },
{ x1 + leftInset, y1 + topInset },
{ x1, y1 + topInset }
};
u32 inds[6] = QUAD_INDICES_ARR;
push_polygon(verts, nullptr, 4, inds, 6, color, nullptr);
}
generate_filled_ellipse_stroke({cx1, cy1}, radius, radius, M_PI, color, segments); // TL
generate_filled_ellipse_stroke({cx2, cy1}, radius, radius, 1.5f * M_PI, color, segments); // TR
generate_filled_ellipse_stroke({cx2, cy2}, radius, radius, 0.0f, color, segments); // BR
generate_filled_ellipse_stroke({cx1, cy2}, radius, radius, 0.5f * M_PI, color, segments); // BL
}
// Top-right gap
if (rTR < topInset)
{
Vec2 verts[4] = {
{ x2 - rightInset, y1 + rTR },
{ x2, y1 + rTR },
{ x2, y1 + topInset },
{ x2 - rightInset, y1 + topInset }
};
u32 inds[6] = QUAD_INDICES_ARR;
push_polygon(verts, nullptr, 4, inds, 6, color, nullptr);
}
void BasicRenderer2D::fillRoundRect(const Vec2& center, const Vec2& size, const Color& color, f32 radius)
{
fillRoundRect({ center.x - size.x * 0.5f, center.y - size.y * 0.5f, size.x, size.y }, color, radius);
// Bottom-left gap
if (rBL < bottomInset)
{
Vec2 verts[4] = {
{ x1, y2 - bottomInset },
{ x1 + leftInset, y2 - bottomInset },
{ x1 + leftInset, y2 - rBL },
{ x1, y2 - rBL }
};
u32 inds[6] = QUAD_INDICES_ARR;
push_polygon(verts, nullptr, 4, inds, 6, color, nullptr);
}
// Bottom-right gap
if (rBR < bottomInset)
{
Vec2 verts[4] = {
{ x2 - rightInset, y2 - bottomInset },
{ x2, y2 - bottomInset },
{ x2, y2 - rBR },
{ x2 - rightInset, y2 - rBR }
};
u32 inds[6] = QUAD_INDICES_ARR;
push_polygon(verts, nullptr, 4, inds, 6, color, nullptr);
}
// Left-side gap (if rTL != rBL, leftInset is the max, smaller one needs a gap)
if (rTL < leftInset && rTL < topInset)
{
// Already covered by TL gap above
}
if (rBL < leftInset && rBL < bottomInset)
{
// Already covered by BL gap above
}
// Corner fills
auto segments = [](f32 r) -> i32 { return std::max(6, i32(r * 0.75f)); };
if (rTL > 0) generate_filled_ellipse_stroke({ x1 + rTL, y1 + rTL }, rTL, rTL, M_PI, color, segments(rTL));
if (rTR > 0) generate_filled_ellipse_stroke({ x2 - rTR, y1 + rTR }, rTR, rTR, M_PI * 1.5f, color, segments(rTR));
if (rBR > 0) generate_filled_ellipse_stroke({ x2 - rBR, y2 - rBR }, rBR, rBR, 0.0f, color, segments(rBR));
if (rBL > 0) generate_filled_ellipse_stroke({ x1 + rBL, y2 - rBL }, rBL, rBL, M_PI * 0.5f, color, segments(rBL));
}
void BasicRenderer2D::fillCircle(const Vec2& center, f32 radius, const Color& color)
@ -714,9 +787,9 @@ namespace ogfx
u32 inds[3] = { 0, 1, 2 };
push_polygon(verts, texCoords, 3, inds, 3, color, nullptr);
}
void BasicRenderer2D::outlinedRect(const Rectangle& rect, const Color& fillColor, const Color& outlineColor, i32 outlineThickness)
{
@ -733,15 +806,25 @@ namespace ogfx
void BasicRenderer2D::outlinedRoundRect(const Rectangle& rect, const Color& fillColor, const Color& outlineColor, f32 radius, i32 outlineThickness)
{
if (!m_initialized) return;
Rectangle offset = { 1, 1, -2, -2 };
fillRoundRect(rect + offset, fillColor, radius);
drawRoundRect(rect, outlineColor, radius, outlineThickness);
outlinedRoundRect(rect, fillColor, outlineColor, { radius, radius, radius, radius }, outlineThickness);
}
void BasicRenderer2D::outlinedRoundRect(const Vec2& center, const Vec2& size, const Color& fillColor, const Color& outlineColor, f32 radius, i32 outlineThickness)
{
outlinedRoundRect({ center.x - size.x * 0.5f, center.y - size.y * 0.5f, size.x, size.y }, fillColor, outlineColor, radius, outlineThickness);
outlinedRoundRect({ center.x - size.x * 0.5f, center.y - size.y * 0.5f, size.x, size.y }, fillColor, outlineColor, { radius, radius, radius, radius }, outlineThickness);
}
void BasicRenderer2D::outlinedRoundRect(const Vec2& center, const Vec2& size, const Color& fillColor, const Color& outlineColor, const Rectangle& radii, i32 outlineThickness)
{
outlinedRoundRect({ center.x - size.x * 0.5f, center.y - size.y * 0.5f, size.x, size.y }, fillColor, outlineColor, radii, outlineThickness);
}
void BasicRenderer2D::outlinedRoundRect(const Rectangle& rect, const Color& fillColor, const Color& outlineColor, const Rectangle& radii, i32 outlineThickness)
{
if (!m_initialized) return;
Rectangle offset = { 1, 1, -2, -2 };
fillRoundRect(rect + offset, fillColor, radii);
drawRoundRect(rect, outlineColor, radii, outlineThickness);
}
void BasicRenderer2D::outlinedCircle(const Vec2& center, f32 radius, const Color& fillColor, const Color& outlineColor, i32 outlineThickness)

View file

@ -93,6 +93,8 @@ namespace ogfx
void drawRect(const Vec2& center, const Vec2& size, const Color& color, i32 thickness = 1);
void drawRoundRect(const Vec2& center, const Vec2& size, const Color& color, f32 radius, i32 thickness = 1);
void drawRoundRect(const Rectangle& rect, const Color& color, f32 radius, i32 thickness = 1);
void drawRoundRect(const Rectangle& rect, const Color& color, const Rectangle& radii, i32 thickness = 1);
void drawRoundRect(const Vec2& center, const Vec2& size, const Color& color, const Rectangle& radii, i32 thickness = 1);
void drawCircle(const Vec2& center, f32 radius, const Color& color, i32 thickness = 1);
void drawCircle(const Rectangle& rect, const Color& color, i32 thickness = 1);
void drawEllipse(const Rectangle& rect, const Color& color, i32 thickness = 1);
@ -103,6 +105,8 @@ namespace ogfx
void fillRect(const Vec2& center, const Vec2& size, const Color& color);
void fillRoundRect(const Rectangle& rect, const Color& color, f32 radius);
void fillRoundRect(const Vec2& center, const Vec2& size, const Color& color, f32 radius);
void fillRoundRect(const Rectangle& rect, const Color& color, const Rectangle& radii);
void fillRoundRect(const Vec2& center, const Vec2& size, const Color& color, const Rectangle& radii);
void fillCircle(const Vec2& center, f32 radius, const Color& color);
void fillCircle(const Rectangle& rect, const Color& color);
void fillEllipse(const Rectangle& rect, const Color& color);
@ -113,6 +117,8 @@ namespace ogfx
void outlinedRect(const Rectangle& rect, const Color& fillColor, const Color& outlineColor, i32 outlineThickness = 1);
void outlinedRoundRect(const Rectangle& rect, const Color& fillColor, const Color& outlineColor, f32 radius, i32 outlineThickness = 1);
void outlinedRoundRect(const Vec2& center, const Vec2& size, const Color& fillColor, const Color& outlineColor, f32 radius, i32 outlineThickness = 1);
void outlinedRoundRect(const Rectangle& rect, const Color& fillColor, const Color& outlineColor, const Rectangle& radii, i32 outlineThickness = 1);
void outlinedRoundRect(const Vec2& center, const Vec2& size, const Color& fillColor, const Color& outlineColor, const Rectangle& radii, i32 outlineThickness = 1);
void outlinedCircle(const Vec2& center, f32 radius, const Color& fillColor, const Color& outlineColor, i32 outlineThickness = 1);
void outlinedCircle(const Rectangle& rect, const Color& fillColor, const Color& outlineColor, i32 outlineThickness = 1);
void outlinedEllipse(const Rectangle& rect, const Color& fillColor, const Color& outlineColor, i32 outlineThickness = 1);

View file

@ -217,7 +217,7 @@ custom_continue:
{
auto it = m_values.find(fullKey);
// if (it != m_values.end())
// std::cout << " GET: " << fullKey << "\n";
// std::cout << " GET: " << fullKey << "\n";
return it != m_values.end() ? &it->second : nullptr;
}
@ -231,6 +231,24 @@ custom_continue:
if (key == "")
return false;
String themeID = "";
auto l_parseColor = [this](const String& _value) -> String {
String value = _value.new_toLower().trim();
if (value.startsWith("color(") && value.endsWith(")"))
{
value.substr(6, value.len() - 1).trim();
return value;
}
else if ((value.startsWith("#") && (value.len() == 7 || value.len() == 9)) ||
(value.startsWith("rgb(") && value.endsWith(")")) ||
(value.startsWith("rgba(") && value.endsWith(")")))
{
return value;
}
return "";
};
if (key.startsWith("@"))
{
if (key.indexOf(" ") < 2)
@ -249,10 +267,9 @@ custom_continue:
valuePreserveCase.substr(1, value.len() - 1);
set(key, valuePreserveCase, themeID);
}
else if (value.startsWith("color(") && value.endsWith(")"))
else if (String v = l_parseColor(value); v != "")
{
value.substr(6, value.len() - 1).trim();
set(key, Color(value), themeID);
set(key, Color(v), themeID);
}
else if (value.startsWith("vec2(") && value.endsWith(")"))
{
@ -284,6 +301,11 @@ custom_continue:
}
set(key, Rectangle(vec[0], vec[1], vec[2], vec[3]), themeID);
}
else if (exitCondition)
{
//Defaulting anything that isn't recognized as any value_type/variable to String type
set(key, valuePreserveCase, themeID);
}
else
{
if (exitCondition)

View file

@ -153,8 +153,7 @@ class Window : public ogfx::gui::Window
void onRedraw(ogfx::BasicRenderer2D& gfx) override
{
gfx.drawAnimation(m_anim, { 200, 200 });
gfx.outlinedTriangle({ 30, 30 }, { 100, 50 }, { 60, 90 }, Colors::Crimson, Colors::DarkBlue, 5);
gfx.endFrame();
gfx.outlinedTriangle({ 30, 30 }, { 100, 50 }, { 60, 90 }, { 255, 0, 0, 80 }, Colors::DarkBlue, 5);
}
void onFixedUpdate(void) override