Browse Source

Remove useless polygons from StyleBoxFlat drawing

David Giardi 2 years ago
parent
commit
16f6f40669
1 changed files with 38 additions and 24 deletions
  1. 38 24
      scene/resources/style_box.cpp

+ 38 - 24
scene/resources/style_box.cpp

@@ -562,8 +562,8 @@ inline void set_inner_corner_radius(const Rect2 style_rect, const Rect2 inner_re
 	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 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 Vector2 &skew, bool fill_center = false) {
+inline void draw_rounded_rectangle(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 Vector2 &skew, bool is_filled = false) {
 	int vert_offset = verts.size();
 	if (!vert_offset) {
 		vert_offset = 0;
@@ -571,6 +571,8 @@ 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;
 
+	bool draw_border = !is_filled;
+
 	real_t ring_corner_radius[4];
 	set_inner_corner_radius(style_rect, ring_rect, corner_radius, ring_corner_radius);
 
@@ -592,9 +594,14 @@ inline void draw_ring(Vector<Vector2> &verts, Vector<int> &indices, Vector<Color
 		Point2(inner_rect.position.x + inner_corner_radius[3], inner_rect.position.y + inner_rect.size.y - inner_corner_radius[3]) //bl
 	};
 	// Calculate the vertices.
+
+	// If the center is filled, we do not draw the border and directly use the inner ring as reference. Because all calls to this
+	// method either draw a ring or a filled rounded rectangle, but not both.
+	int max_inner_outer = draw_border ? 2 : 1;
+
 	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++) {
+			for (int inner_outer = 0; inner_outer < max_inner_outer; inner_outer++) {
 				real_t radius;
 				Color color;
 				Point2 corner_point;
@@ -621,24 +628,31 @@ 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.
-	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));
-		indices.push_back(vert_offset + ((i + 1) % ring_vert_count));
+
+	if (draw_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));
+			indices.push_back(vert_offset + ((i + 1) % ring_vert_count));
+		}
 	}
 
-	if (fill_center) {
-		//Fill the indices and the colors for the center.
-		for (int index = 0; index < ring_vert_count / 2; index += 2) {
-			int i = index;
+	if (is_filled) {
+		// Compute the triangles pattern to draw the rounded rectangle.
+		// Consists of vertical stripes of two triangles each.
+
+		int stripes_count = ring_vert_count / 2 - 1;
+		int last_vert_id = ring_vert_count - 1;
+
+		for (int i = 0; i < stripes_count; i++) {
 			// 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);
+			indices.push_back(vert_offset + last_vert_id - i - 1);
+			indices.push_back(vert_offset + i + 1);
 			// 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);
+			indices.push_back(vert_offset + last_vert_id - 0 - i);
+			indices.push_back(vert_offset + last_vert_id - 1 - i);
 		}
 	}
 }
@@ -741,24 +755,24 @@ void StyleBoxFlat::draw(RID p_canvas_item, const Rect2 &p_rect) const {
 
 		Color shadow_color_transparent = Color(shadow_color.r, shadow_color.g, shadow_color.b, 0);
 
-		draw_ring(verts, indices, colors, shadow_inner_rect, adapted_corner,
+		draw_rounded_rectangle(verts, indices, colors, shadow_inner_rect, adapted_corner,
 				shadow_rect, shadow_inner_rect, shadow_color, shadow_color_transparent, corner_detail, skew);
 
 		if (draw_center) {
-			draw_ring(verts, indices, colors, shadow_inner_rect, adapted_corner,
+			draw_rounded_rectangle(verts, indices, colors, shadow_inner_rect, adapted_corner,
 					shadow_inner_rect, shadow_inner_rect, shadow_color, shadow_color, corner_detail, skew, true);
 		}
 	}
 
 	// Create border (no AA).
 	if (draw_border && !aa_on) {
-		draw_ring(verts, indices, colors, border_style_rect, adapted_corner,
+		draw_rounded_rectangle(verts, indices, colors, border_style_rect, adapted_corner,
 				border_style_rect, infill_rect, border_color_inner, border_color, corner_detail, skew);
 	}
 
 	// Create infill (no AA).
 	if (draw_center && (!aa_on || blend_on)) {
-		draw_ring(verts, indices, colors, border_style_rect, adapted_corner,
+		draw_rounded_rectangle(verts, indices, colors, border_style_rect, adapted_corner,
 				infill_rect, infill_rect, bg_color, bg_color, corner_detail, skew, true);
 	}
 
@@ -799,13 +813,13 @@ void StyleBoxFlat::draw(RID p_canvas_item, const Rect2 &p_rect) const {
 					-aa_fill_width[SIDE_RIGHT], -aa_fill_width[SIDE_BOTTOM]);
 			if (!blend_on) {
 				// Create center fill, not antialiased yet
-				draw_ring(verts, indices, colors, border_style_rect, adapted_corner,
+				draw_rounded_rectangle(verts, indices, colors, border_style_rect, adapted_corner,
 						infill_rect_aa_colored, infill_rect_aa_colored, bg_color, bg_color, corner_detail, skew, true);
 			}
 			if (!blend_on || !draw_border) {
 				Color alpha_bg = Color(bg_color.r, bg_color.g, bg_color.b, 0);
 				// Add antialiasing on the center fill
-				draw_ring(verts, indices, colors, border_style_rect, adapted_corner,
+				draw_rounded_rectangle(verts, indices, colors, border_style_rect, adapted_corner,
 						infill_rect_aa_transparent, infill_rect_aa_colored, bg_color, alpha_bg, corner_detail, skew);
 			}
 		}
@@ -825,15 +839,15 @@ void StyleBoxFlat::draw(RID p_canvas_item, const Rect2 &p_rect) const {
 					aa_border_width_half[SIDE_RIGHT], aa_border_width_half[SIDE_BOTTOM]);
 
 			// Create border ring, not antialiased yet
-			draw_ring(verts, indices, colors, border_style_rect, adapted_corner,
+			draw_rounded_rectangle(verts, indices, colors, border_style_rect, adapted_corner,
 					outer_rect_aa_colored, ((blend_on) ? infill_rect : inner_rect_aa_colored), border_color_inner, border_color, corner_detail, skew);
 			if (!blend_on) {
 				// Add antialiasing on the ring inner border
-				draw_ring(verts, indices, colors, border_style_rect, adapted_corner,
+				draw_rounded_rectangle(verts, indices, colors, border_style_rect, adapted_corner,
 						inner_rect_aa_colored, inner_rect_aa_transparent, border_color_blend, border_color, corner_detail, skew);
 			}
 			// Add antialiasing on the ring outer border
-			draw_ring(verts, indices, colors, border_style_rect, adapted_corner,
+			draw_rounded_rectangle(verts, indices, colors, border_style_rect, adapted_corner,
 					outer_rect_aa_transparent, outer_rect_aa_colored, border_color, border_color_alpha, corner_detail, skew);
 		}
 	}