Merge pull request #51442 from Geometror/styleboxflat-fake-aa-float

StyleBox fake AA improvements (make anti aliasing size a float property)
This commit is contained in:
Rémi Verschelde 2021-08-11 07:35:53 +02:00 committed by GitHub
commit 588883eb4a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 84 additions and 86 deletions

View file

@ -121,7 +121,7 @@
<member name="anti_aliasing" type="bool" setter="set_anti_aliased" getter="is_anti_aliased" default="true">
Antialiasing draws a small ring around the edges, which fades to transparency. As a result, edges look much smoother. This is only noticeable when using rounded corners.
</member>
<member name="anti_aliasing_size" type="int" setter="set_aa_size" getter="get_aa_size" default="1">
<member name="anti_aliasing_size" type="float" setter="set_aa_size" getter="get_aa_size" default="0.625">
This changes the size of the faded ring. Higher values can be used to achieve a "blurry" effect.
</member>
<member name="bg_color" type="Color" setter="set_bg_color" getter="get_bg_color" default="Color(0.6, 0.6, 0.6, 1)">

View file

@ -87,9 +87,6 @@ void StyleBox::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_default_margin", "margin", "offset"), &StyleBox::set_default_margin);
ClassDB::bind_method(D_METHOD("get_default_margin", "margin"), &StyleBox::get_default_margin);
//ClassDB::bind_method(D_METHOD("set_default_margin"),&StyleBox::set_default_margin);
//ClassDB::bind_method(D_METHOD("get_default_margin"),&StyleBox::get_default_margin);
ClassDB::bind_method(D_METHOD("get_margin", "margin"), &StyleBox::get_margin);
ClassDB::bind_method(D_METHOD("get_minimum_size"), &StyleBox::get_minimum_size);
ClassDB::bind_method(D_METHOD("get_center_size"), &StyleBox::get_center_size);
@ -464,12 +461,12 @@ bool StyleBoxFlat::is_anti_aliased() const {
return anti_aliased;
}
void StyleBoxFlat::set_aa_size(const int &p_aa_size) {
aa_size = CLAMP(p_aa_size, 1, 5);
void StyleBoxFlat::set_aa_size(const real_t &p_aa_size) {
aa_size = CLAMP(p_aa_size, 0.01, 10);
emit_changed();
}
int StyleBoxFlat::get_aa_size() const {
float StyleBoxFlat::get_aa_size() const {
return aa_size;
}
@ -486,31 +483,32 @@ Size2 StyleBoxFlat::get_center_size() const {
return Size2();
}
inline void set_inner_corner_radius(const Rect2 style_rect, const Rect2 inner_rect, const int corner_radius[4], int *inner_corner_radius) {
int border_left = inner_rect.position.x - style_rect.position.x;
int border_top = inner_rect.position.y - style_rect.position.y;
int border_right = style_rect.size.width - inner_rect.size.width - border_left;
int border_bottom = style_rect.size.height - inner_rect.size.height - border_top;
inline void set_inner_corner_radius(const Rect2 style_rect, const Rect2 inner_rect, const real_t corner_radius[4], real_t *inner_corner_radius) {
real_t border_left = inner_rect.position.x - style_rect.position.x;
real_t border_top = inner_rect.position.y - style_rect.position.y;
real_t border_right = style_rect.size.width - inner_rect.size.width - border_left;
real_t border_bottom = style_rect.size.height - inner_rect.size.height - border_top;
int rad;
//tl
real_t rad;
// Top left.
rad = MIN(border_top, border_left);
inner_corner_radius[0] = MAX(corner_radius[0] - rad, 0);
//tr
// Top right;
rad = MIN(border_top, border_right);
inner_corner_radius[1] = MAX(corner_radius[1] - rad, 0);
//br
// Bottom right.
rad = MIN(border_bottom, border_right);
inner_corner_radius[2] = MAX(corner_radius[2] - rad, 0);
//bl
// Bottom left.
rad = MIN(border_bottom, border_left);
inner_corner_radius[3] = MAX(corner_radius[3] - rad, 0);
}
inline void draw_ring(Vector<Vector2> &verts, Vector<int> &indices, Vector<Color> &colors, const Rect2 &style_rect, const int corner_radius[4],
inline void draw_ring(Vector<Vector2> &verts, Vector<int> &indices, Vector<Color> &colors, const Rect2 &style_rect, const real_t corner_radius[4],
const Rect2 &ring_rect, const Rect2 &inner_rect, const Color &inner_color, const Color &outer_color, const int corner_detail, const bool fill_center = false) {
int vert_offset = verts.size();
if (!vert_offset) {
@ -519,17 +517,17 @@ inline void draw_ring(Vector<Vector2> &verts, Vector<int> &indices, Vector<Color
int adapted_corner_detail = (corner_radius[0] == 0 && corner_radius[1] == 0 && corner_radius[2] == 0 && corner_radius[3] == 0) ? 1 : corner_detail;
int ring_corner_radius[4];
real_t ring_corner_radius[4];
set_inner_corner_radius(style_rect, ring_rect, corner_radius, ring_corner_radius);
//corner radius center points
// Corner radius center points.
Vector<Point2> outer_points;
outer_points.push_back(ring_rect.position + Vector2(ring_corner_radius[0], ring_corner_radius[0])); //tl
outer_points.push_back(Point2(ring_rect.position.x + ring_rect.size.x - ring_corner_radius[1], ring_rect.position.y + ring_corner_radius[1])); //tr
outer_points.push_back(ring_rect.position + ring_rect.size - Vector2(ring_corner_radius[2], ring_corner_radius[2])); //br
outer_points.push_back(Point2(ring_rect.position.x + ring_corner_radius[3], ring_rect.position.y + ring_rect.size.y - ring_corner_radius[3])); //bl
int inner_corner_radius[4];
real_t inner_corner_radius[4];
set_inner_corner_radius(style_rect, inner_rect, corner_radius, inner_corner_radius);
Vector<Point2> inner_points;
@ -538,11 +536,11 @@ inline void draw_ring(Vector<Vector2> &verts, Vector<int> &indices, Vector<Color
inner_points.push_back(inner_rect.position + inner_rect.size - Vector2(inner_corner_radius[2], inner_corner_radius[2])); //br
inner_points.push_back(Point2(inner_rect.position.x + inner_corner_radius[3], inner_rect.position.y + inner_rect.size.y - inner_corner_radius[3])); //bl
//calculate the vert array
// Calculate the vertices.
for (int corner_index = 0; corner_index < 4; corner_index++) {
for (int detail = 0; detail <= adapted_corner_detail; detail++) {
for (int inner_outer = 0; inner_outer < 2; inner_outer++) {
float radius;
real_t radius;
Color color;
Point2 corner_point;
if (inner_outer == 0) {
@ -564,7 +562,7 @@ inline void draw_ring(Vector<Vector2> &verts, Vector<int> &indices, Vector<Color
int ring_vert_count = verts.size() - vert_offset;
//fill the indices and the colors for the border
// Fill the indices and the colors for the border.
for (int i = 0; i < ring_vert_count; i++) {
indices.push_back(vert_offset + ((i + 0) % ring_vert_count));
indices.push_back(vert_offset + ((i + 2) % ring_vert_count));
@ -572,14 +570,14 @@ inline void draw_ring(Vector<Vector2> &verts, Vector<int> &indices, Vector<Color
}
if (fill_center) {
//fill the indices and the colors for the center
//Fill the indices and the colors for the center.
for (int index = 0; index < ring_vert_count / 2; index += 2) {
int i = index;
//poly 1
// Polygon 1.
indices.push_back(vert_offset + i);
indices.push_back(vert_offset + ring_vert_count - 4 - i);
indices.push_back(vert_offset + i + 2);
//poly 2
// Polygon 2.
indices.push_back(vert_offset + i);
indices.push_back(vert_offset + ring_vert_count - 2 - i);
indices.push_back(vert_offset + ring_vert_count - 4 - i);
@ -587,20 +585,20 @@ inline void draw_ring(Vector<Vector2> &verts, Vector<int> &indices, Vector<Color
}
}
inline void adapt_values(int p_index_a, int p_index_b, int *adapted_values, const int *p_values, const real_t p_width, const int p_max_a, const int p_max_b) {
inline void adapt_values(int p_index_a, int p_index_b, real_t *adapted_values, const real_t *p_values, const real_t p_width, const real_t p_max_a, const real_t p_max_b) {
if (p_values[p_index_a] + p_values[p_index_b] > p_width) {
float factor;
int newValue;
real_t factor;
real_t new_value;
factor = (float)p_width / (float)(p_values[p_index_a] + p_values[p_index_b]);
factor = (real_t)p_width / (real_t)(p_values[p_index_a] + p_values[p_index_b]);
newValue = (int)(p_values[p_index_a] * factor);
if (newValue < adapted_values[p_index_a]) {
adapted_values[p_index_a] = newValue;
new_value = (p_values[p_index_a] * factor);
if (new_value < adapted_values[p_index_a]) {
adapted_values[p_index_a] = new_value;
}
newValue = (int)(p_values[p_index_b] * factor);
if (newValue < adapted_values[p_index_b]) {
adapted_values[p_index_b] = newValue;
new_value = (p_values[p_index_b] * factor);
if (new_value < adapted_values[p_index_b]) {
adapted_values[p_index_b] = new_value;
}
} else {
adapted_values[p_index_a] = MIN(p_values[p_index_a], adapted_values[p_index_a]);
@ -623,7 +621,6 @@ Rect2 StyleBoxFlat::get_draw_rect(const Rect2 &p_rect) const {
}
void StyleBoxFlat::draw(RID p_canvas_item, const Rect2 &p_rect) const {
//PREPARATIONS
bool draw_border = (border_width[0] > 0) || (border_width[1] > 0) || (border_width[2] > 0) || (border_width[3] > 0);
bool draw_shadow = (shadow_size > 0);
if (!draw_border && !draw_center && !draw_shadow) {
@ -637,7 +634,6 @@ void StyleBoxFlat::draw(RID p_canvas_item, const Rect2 &p_rect) const {
bool rounded_corners = (corner_radius[0] > 0) || (corner_radius[1] > 0) || (corner_radius[2] > 0) || (corner_radius[3] > 0);
bool aa_on = rounded_corners && anti_aliased;
float aa_size_grow = 0.5 * ((float)aa_size + 1.0);
bool blend_on = blend_border && draw_border;
@ -645,15 +641,15 @@ void StyleBoxFlat::draw(RID p_canvas_item, const Rect2 &p_rect) const {
Color border_color_blend = (draw_center ? bg_color : border_color_alpha);
Color border_color_inner = blend_on ? border_color_blend : border_color;
//adapt borders (prevent weird overlapping/glitchy drawings)
int width = MAX(style_rect.size.width, 0);
int height = MAX(style_rect.size.height, 0);
int adapted_border[4] = { INT_MAX, INT_MAX, INT_MAX, INT_MAX };
// Adapt borders (prevent weird overlapping/glitchy drawings).
real_t width = MAX(style_rect.size.width, 0);
real_t height = MAX(style_rect.size.height, 0);
real_t adapted_border[4] = { 1000000.0, 1000000.0, 1000000.0, 1000000.0 };
adapt_values(SIDE_TOP, SIDE_BOTTOM, adapted_border, border_width, height, height, height);
adapt_values(SIDE_LEFT, SIDE_RIGHT, adapted_border, border_width, width, width, width);
//adapt corners (prevent weird overlapping/glitchy drawings)
int adapted_corner[4] = { INT_MAX, INT_MAX, INT_MAX, INT_MAX };
// Adapt corners (prevent weird overlapping/glitchy drawings).
real_t adapted_corner[4] = { 1000000.0, 1000000.0, 1000000.0, 1000000.0 };
adapt_values(CORNER_TOP_RIGHT, CORNER_BOTTOM_RIGHT, adapted_corner, corner_radius, height, height - adapted_border[SIDE_BOTTOM], height - adapted_border[SIDE_TOP]);
adapt_values(CORNER_TOP_LEFT, CORNER_BOTTOM_LEFT, adapted_corner, corner_radius, height, height - adapted_border[SIDE_BOTTOM], height - adapted_border[SIDE_TOP]);
adapt_values(CORNER_TOP_LEFT, CORNER_TOP_RIGHT, adapted_corner, corner_radius, width, width - adapted_border[SIDE_RIGHT], width - adapted_border[SIDE_LEFT]);
@ -665,7 +661,7 @@ void StyleBoxFlat::draw(RID p_canvas_item, const Rect2 &p_rect) const {
if (aa_on) {
for (int i = 0; i < 4; i++) {
if (border_width[i] > 0) {
border_style_rect = border_style_rect.grow_side((Side)i, -aa_size_grow);
border_style_rect = border_style_rect.grow_side((Side)i, -aa_size);
}
}
}
@ -675,7 +671,7 @@ void StyleBoxFlat::draw(RID p_canvas_item, const Rect2 &p_rect) const {
Vector<Color> colors;
Vector<Point2> uvs;
//DRAW SHADOW
// Create shadow
if (draw_shadow) {
Rect2 shadow_inner_rect = style_rect;
shadow_inner_rect.position += shadow_offset;
@ -694,35 +690,35 @@ void StyleBoxFlat::draw(RID p_canvas_item, const Rect2 &p_rect) const {
}
}
//DRAW border
if (draw_border) {
// Create border (no AA).
if (draw_border && !aa_on) {
draw_ring(verts, indices, colors, border_style_rect, adapted_corner,
border_style_rect, infill_rect, border_color_inner, border_color, corner_detail);
}
//DRAW INFILL
// Create infill (no AA).
if (draw_center && (!aa_on || blend_on || !draw_border)) {
draw_ring(verts, indices, colors, border_style_rect, adapted_corner,
infill_rect, infill_rect, bg_color, bg_color, corner_detail, true);
}
if (aa_on) {
int aa_border_width[4];
int aa_fill_width[4];
real_t aa_border_width[4];
real_t aa_fill_width[4];
if (draw_border) {
for (int i = 0; i < 4; i++) {
if (border_width[i] > 0) {
aa_border_width[i] = aa_size_grow;
aa_border_width[i] = aa_size;
aa_fill_width[i] = 0;
} else {
aa_border_width[i] = 0;
aa_fill_width[i] = aa_size_grow;
aa_fill_width[i] = aa_size;
}
}
} else {
for (int i = 0; i < 4; i++) {
aa_border_width[i] = 0;
aa_fill_width[i] = aa_size_grow;
aa_fill_width[i] = aa_size;
}
}
@ -731,45 +727,58 @@ void StyleBoxFlat::draw(RID p_canvas_item, const Rect2 &p_rect) const {
if (draw_center) {
if (!blend_on && draw_border) {
//DRAW INFILL WITHIN BORDER AA
Rect2 infill_inner_rect_aa = infill_inner_rect.grow_individual(aa_border_width[SIDE_LEFT], aa_border_width[SIDE_TOP],
aa_border_width[SIDE_RIGHT], aa_border_width[SIDE_BOTTOM]);
// Create infill within AA border.
draw_ring(verts, indices, colors, border_style_rect, adapted_corner,
infill_inner_rect, infill_inner_rect, bg_color, bg_color, corner_detail, true);
infill_inner_rect_aa, infill_inner_rect_aa, bg_color, bg_color, corner_detail, true);
}
if (!blend_on || !draw_border) {
Rect2 infill_aa_rect = infill_rect.grow_individual(aa_fill_width[SIDE_LEFT], aa_fill_width[SIDE_TOP],
Rect2 infill_rect_aa = infill_rect.grow_individual(aa_fill_width[SIDE_LEFT], aa_fill_width[SIDE_TOP],
aa_fill_width[SIDE_RIGHT], aa_fill_width[SIDE_BOTTOM]);
Color alpha_bg = Color(bg_color.r, bg_color.g, bg_color.b, 0);
//INFILL AA
// Create infill fake AA gradient.
draw_ring(verts, indices, colors, style_rect, adapted_corner,
infill_aa_rect, infill_rect, bg_color, alpha_bg, corner_detail);
infill_rect_aa, infill_rect, bg_color, alpha_bg, corner_detail);
}
}
if (draw_border) {
Rect2 infill_rect_aa = infill_rect.grow_individual(aa_border_width[SIDE_LEFT], aa_border_width[SIDE_TOP],
aa_border_width[SIDE_RIGHT], aa_border_width[SIDE_BOTTOM]);
Rect2 style_rect_aa = style_rect.grow_individual(aa_border_width[SIDE_LEFT], aa_border_width[SIDE_TOP],
aa_border_width[SIDE_RIGHT], aa_border_width[SIDE_BOTTOM]);
Rect2 border_style_rect_aa = border_style_rect.grow_individual(aa_border_width[SIDE_LEFT], aa_border_width[SIDE_TOP],
aa_border_width[SIDE_RIGHT], aa_border_width[SIDE_BOTTOM]);
// Create border.
draw_ring(verts, indices, colors, border_style_rect, adapted_corner,
border_style_rect_aa, ((blend_on) ? infill_rect : infill_rect_aa), border_color_inner, border_color, corner_detail);
if (!blend_on) {
//DRAW INNER BORDER AA
// Create inner border fake AA gradient.
draw_ring(verts, indices, colors, border_style_rect, adapted_corner,
infill_rect, infill_inner_rect, border_color_blend, border_color, corner_detail);
infill_rect_aa, infill_rect, border_color_blend, border_color, corner_detail);
}
//DRAW OUTER BORDER AA
// Create outer border fake AA gradient.
draw_ring(verts, indices, colors, border_style_rect, adapted_corner,
style_rect, border_style_rect, border_color, border_color_alpha, corner_detail);
style_rect_aa, border_style_rect_aa, border_color, border_color_alpha, corner_detail);
}
}
//COMPUTE UV COORDINATES
Rect2 uv_rect = style_rect.grow(aa_on ? aa_size_grow : 0);
// Compute UV coordinates.
Rect2 uv_rect = style_rect.grow(aa_on ? aa_size : 0);
uvs.resize(verts.size());
for (int i = 0; i < verts.size(); i++) {
uvs.write[i].x = (verts[i].x - uv_rect.position.x) / uv_rect.size.width;
uvs.write[i].y = (verts[i].y - uv_rect.position.y) / uv_rect.size.height;
}
//DRAWING
// Draw stylebox.
RenderingServer *vs = RenderingServer::get_singleton();
vs->canvas_item_add_triangle_array(p_canvas_item, indices, verts, colors, uvs);
}
@ -869,7 +878,7 @@ void StyleBoxFlat::_bind_methods() {
ADD_GROUP("Anti Aliasing", "anti_aliasing_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "anti_aliasing"), "set_anti_aliased", "is_anti_aliased");
ADD_PROPERTY(PropertyInfo(Variant::INT, "anti_aliasing_size", PROPERTY_HINT_RANGE, "1,5,1"), "set_aa_size", "get_aa_size");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "anti_aliasing_size", PROPERTY_HINT_RANGE, "0.01,10,0.001"), "set_aa_size", "get_aa_size");
}
StyleBoxFlat::StyleBoxFlat() {}

View file

@ -143,9 +143,9 @@ class StyleBoxFlat : public StyleBox {
Color shadow_color = Color(0, 0, 0, 0.6);
Color border_color = Color(0.8, 0.8, 0.8);
int border_width[4] = {};
int expand_margin[4] = {};
int corner_radius[4] = {};
real_t border_width[4] = {};
real_t expand_margin[4] = {};
real_t corner_radius[4] = {};
bool draw_center = true;
bool blend_border = false;
@ -154,7 +154,7 @@ class StyleBoxFlat : public StyleBox {
int corner_detail = 8;
int shadow_size = 0;
Point2 shadow_offset;
int aa_size = 1;
real_t aa_size = 0.625;
protected:
virtual float get_style_margin(Side p_side) const override;
@ -162,27 +162,21 @@ protected:
void _validate_property(PropertyInfo &property) const override;
public:
//Color
void set_bg_color(const Color &p_color);
Color get_bg_color() const;
//Border Color
void set_border_color(const Color &p_color);
Color get_border_color() const;
//BORDER
//width
void set_border_width_all(int p_size);
int get_border_width_min() const;
void set_border_width(Side p_side, int p_width);
int get_border_width(Side p_side) const;
//blend
void set_border_blend(bool p_blend);
bool get_border_blend() const;
//CORNER
void set_corner_radius_all(int radius);
void set_corner_radius_individual(const int radius_top_left, const int radius_top_right, const int radius_bottom_right, const int radius_bottom_left);
@ -192,17 +186,14 @@ public:
void set_corner_detail(const int &p_corner_detail);
int get_corner_detail() const;
//EXPANDS
void set_expand_margin_size(Side p_expand_side, float p_size);
void set_expand_margin_size_all(float p_expand_margin_size);
void set_expand_margin_size_individual(float p_left, float p_top, float p_right, float p_bottom);
float get_expand_margin_size(Side p_expand_side) const;
//DRAW CENTER
void set_draw_center(bool p_enabled);
bool is_draw_center_enabled() const;
//SHADOW
void set_shadow_color(const Color &p_color);
Color get_shadow_color() const;
@ -212,12 +203,10 @@ public:
void set_shadow_offset(const Point2 &p_offset);
Point2 get_shadow_offset() const;
//ANTI_ALIASING
void set_anti_aliased(const bool &p_anti_aliased);
bool is_anti_aliased() const;
//tempAA
void set_aa_size(const int &p_aa_size);
int get_aa_size() const;
void set_aa_size(const float &p_aa_size);
float get_aa_size() const;
virtual Size2 get_center_size() const override;
@ -228,7 +217,7 @@ public:
~StyleBoxFlat();
};
// just used to draw lines.
// Just used to draw lines.
class StyleBoxLine : public StyleBox {
GDCLASS(StyleBoxLine, StyleBox);
Color color;