Browse Source

StyleBox fake AA improvements (aa_size float property)

Hendrik Brucker 4 years ago
parent
commit
db2460f43c
3 changed files with 84 additions and 86 deletions
  1. 1 1
      doc/classes/StyleBoxFlat.xml
  2. 76 67
      scene/resources/style_box.cpp
  3. 7 18
      scene/resources/style_box.h

+ 1 - 1
doc/classes/StyleBoxFlat.xml

@@ -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)">

+ 76 - 67
scene/resources/style_box.cpp

@@ -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;
+
+	real_t rad;
 
-	int rad;
-	//tl
+	// 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() {}

+ 7 - 18
scene/resources/style_box.h

@@ -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;