summaryrefslogtreecommitdiff
path: root/scene/2d/line_builder.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'scene/2d/line_builder.cpp')
-rw-r--r--scene/2d/line_builder.cpp120
1 files changed, 79 insertions, 41 deletions
diff --git a/scene/2d/line_builder.cpp b/scene/2d/line_builder.cpp
index eb09d3c9d3..9fe5fb98b6 100644
--- a/scene/2d/line_builder.cpp
+++ b/scene/2d/line_builder.cpp
@@ -95,6 +95,7 @@ static inline Vector2 interpolate(const Rect2 &r, const Vector2 &v) {
LineBuilder::LineBuilder() {
joint_mode = Line2D::LINE_JOINT_SHARP;
width = 10;
+ curve = NULL;
default_color = Color(0.4, 0.5, 1);
gradient = NULL;
sharp_limit = 2.f;
@@ -136,8 +137,8 @@ void LineBuilder::build() {
Vector2 pos1 = points[1];
Vector2 f0 = (pos1 - pos0).normalized();
Vector2 u0 = rotate90(f0);
- Vector2 pos_up0 = pos0 + u0 * hw;
- Vector2 pos_down0 = pos0 - u0 * hw;
+ Vector2 pos_up0 = pos0;
+ Vector2 pos_down0 = pos0;
Color color0;
Color color1;
@@ -145,12 +146,30 @@ void LineBuilder::build() {
float current_distance0 = 0.f;
float current_distance1 = 0.f;
float total_distance = 0.f;
+ float width_factor = 1.f;
_interpolate_color = gradient != NULL;
+ bool retrieve_curve = curve != NULL;
bool distance_required = _interpolate_color ||
+ retrieve_curve ||
texture_mode == Line2D::LINE_TEXTURE_TILE ||
texture_mode == Line2D::LINE_TEXTURE_STRETCH;
- if (distance_required)
+ if (distance_required) {
total_distance = calculate_total_distance(points);
+ //Ajust totalDistance.
+ // The line's outer length will be a little higher due to begin and end caps
+ if (begin_cap_mode == Line2D::LINE_CAP_BOX || begin_cap_mode == Line2D::LINE_CAP_ROUND) {
+ if (retrieve_curve)
+ total_distance += width * curve->interpolate_baked(0.f) * 0.5f;
+ else
+ total_distance += width * 0.5f;
+ }
+ if (end_cap_mode == Line2D::LINE_CAP_BOX || end_cap_mode == Line2D::LINE_CAP_ROUND) {
+ if (retrieve_curve)
+ total_distance += width * curve->interpolate_baked(1.f) * 0.5f;
+ else
+ total_distance += width * 0.5f;
+ }
+ }
if (_interpolate_color)
color0 = gradient->get_color(0);
else
@@ -159,22 +178,28 @@ void LineBuilder::build() {
float uvx0 = 0.f;
float uvx1 = 0.f;
+ if (retrieve_curve)
+ width_factor = curve->interpolate_baked(0.f);
+
+ pos_up0 += u0 * hw * width_factor;
+ pos_down0 -= u0 * hw * width_factor;
+
// Begin cap
if (begin_cap_mode == Line2D::LINE_CAP_BOX) {
// Push back first vertices a little bit
- pos_up0 -= f0 * hw;
- pos_down0 -= f0 * hw;
- // The line's outer length will be a little higher due to begin and end caps
- total_distance += width;
- current_distance0 += hw;
+ pos_up0 -= f0 * hw * width_factor;
+ pos_down0 -= f0 * hw * width_factor;
+
+ current_distance0 += hw * width_factor;
current_distance1 = current_distance0;
} else if (begin_cap_mode == Line2D::LINE_CAP_ROUND) {
if (texture_mode == Line2D::LINE_TEXTURE_TILE) {
- uvx0 = 0.5f / tile_aspect;
+ uvx0 = width_factor * 0.5f / tile_aspect;
+ } else if (texture_mode == Line2D::LINE_TEXTURE_STRETCH) {
+ uvx0 = width * width_factor / total_distance;
}
- new_arc(pos0, pos_up0 - pos0, -Math_PI, color0, Rect2(0.f, 0.f, fmin(uvx0 * 2, 1.f), 1.f));
- total_distance += width;
- current_distance0 += hw;
+ new_arc(pos0, pos_up0 - pos0, -Math_PI, color0, Rect2(0.f, 0.f, uvx0 * 2, 1.f));
+ current_distance0 += hw * width_factor;
current_distance1 = current_distance0;
}
@@ -206,13 +231,23 @@ void LineBuilder::build() {
const float dp = u0.dot(f1);
const Orientation orientation = (dp > 0.f ? UP : DOWN);
+ if (distance_required) {
+ current_distance1 += pos0.distance_to(pos1);
+ }
+ if (_interpolate_color) {
+ color1 = gradient->get_color_at_offset(current_distance1 / total_distance);
+ }
+ if (retrieve_curve) {
+ width_factor = curve->interpolate_baked(current_distance1 / total_distance);
+ }
+
Vector2 inner_normal0, inner_normal1;
if (orientation == UP) {
- inner_normal0 = u0 * hw;
- inner_normal1 = u1 * hw;
+ inner_normal0 = u0 * hw * width_factor;
+ inner_normal1 = u1 * hw * width_factor;
} else {
- inner_normal0 = -u0 * hw;
- inner_normal1 = -u1 * hw;
+ inner_normal0 = -u0 * hw * width_factor;
+ inner_normal1 = -u1 * hw * width_factor;
}
/*
@@ -259,7 +294,8 @@ void LineBuilder::build() {
Vector2 pos_up1, pos_down1;
if (intersection_result == SEGMENT_INTERSECT) {
// Fallback on bevel if sharp angle is too high (because it would produce very long miters)
- if (current_joint_mode == Line2D::LINE_JOINT_SHARP && corner_pos_out.distance_squared_to(pos1) / hw_sq > sharp_limit_sq) {
+ float width_factor_sq = width_factor * width_factor;
+ if (current_joint_mode == Line2D::LINE_JOINT_SHARP && corner_pos_out.distance_squared_to(pos1) / (hw_sq * width_factor_sq) > sharp_limit_sq) {
current_joint_mode = Line2D::LINE_JOINT_BEVEL;
}
if (current_joint_mode == Line2D::LINE_JOINT_SHARP) {
@@ -271,9 +307,9 @@ void LineBuilder::build() {
// Bevel or round
if (orientation == UP) {
pos_up1 = corner_pos_up;
- pos_down1 = pos1 - u0 * hw;
+ pos_down1 = pos1 - u0 * hw * width_factor;
} else {
- pos_up1 = pos1 + u0 * hw;
+ pos_up1 = pos1 + u0 * hw * width_factor;
pos_down1 = corner_pos_down;
}
}
@@ -289,12 +325,6 @@ void LineBuilder::build() {
// Add current line body quad
// Triangles are clockwise
- if (distance_required) {
- current_distance1 += pos0.distance_to(pos1);
- }
- if (_interpolate_color) {
- color1 = gradient->get_color_at_offset(current_distance1 / total_distance);
- }
if (texture_mode == Line2D::LINE_TEXTURE_TILE) {
uvx1 = current_distance1 / (width * tile_aspect);
} else if (texture_mode == Line2D::LINE_TEXTURE_STRETCH) {
@@ -315,15 +345,15 @@ void LineBuilder::build() {
} else {
if (orientation == UP) {
pos_up0 = corner_pos_up;
- pos_down0 = pos1 - u1 * hw;
+ pos_down0 = pos1 - u1 * hw * width_factor;
} else {
- pos_up0 = pos1 + u1 * hw;
+ pos_up0 = pos1 + u1 * hw * width_factor;
pos_down0 = corner_pos_down;
}
}
} else {
- pos_up0 = pos1 + u1 * hw;
- pos_down0 = pos1 - u1 * hw;
+ pos_up0 = pos1 + u1 * hw * width_factor;
+ pos_down0 = pos1 - u1 * hw * width_factor;
}
// From this point, bu0 and bd0 concern the next segment
@@ -362,26 +392,28 @@ void LineBuilder::build() {
strip_begin(pos_up0, pos_down0, color1, uvx1);
}
}
-
// Last (or only) segment
-
pos1 = points[points.size() - 1];
- Vector2 pos_up1 = pos1 + u0 * hw;
- Vector2 pos_down1 = pos1 - u0 * hw;
-
- // End cap (box)
- if (end_cap_mode == Line2D::LINE_CAP_BOX) {
- pos_up1 += f0 * hw;
- pos_down1 += f0 * hw;
- }
-
if (distance_required) {
current_distance1 += pos0.distance_to(pos1);
}
if (_interpolate_color) {
color1 = gradient->get_color(gradient->get_points_count() - 1);
}
+ if (retrieve_curve) {
+ width_factor = curve->interpolate_baked(1.f);
+ }
+
+ Vector2 pos_up1 = pos1 + u0 * hw * width_factor;
+ Vector2 pos_down1 = pos1 - u0 * hw * width_factor;
+
+ // End cap (box)
+ if (end_cap_mode == Line2D::LINE_CAP_BOX) {
+ pos_up1 += f0 * hw * width_factor;
+ pos_down1 += f0 * hw * width_factor;
+ }
+
if (texture_mode == Line2D::LINE_TEXTURE_TILE) {
uvx1 = current_distance1 / (width * tile_aspect);
} else if (texture_mode == Line2D::LINE_TEXTURE_STRETCH) {
@@ -394,7 +426,13 @@ void LineBuilder::build() {
if (end_cap_mode == Line2D::LINE_CAP_ROUND) {
// Note: color is not used in case we don't interpolate...
Color color = _interpolate_color ? gradient->get_color(gradient->get_points_count() - 1) : Color(0, 0, 0);
- new_arc(pos1, pos_up1 - pos1, Math_PI, color, Rect2(uvx1 - 0.5f / tile_aspect, 0.f, 1.0f / tile_aspect, 1.f));
+ float dist = 0;
+ if (texture_mode == Line2D::LINE_TEXTURE_TILE) {
+ dist = width_factor / tile_aspect;
+ } else if (texture_mode == Line2D::LINE_TEXTURE_STRETCH) {
+ dist = width * width_factor / total_distance;
+ }
+ new_arc(pos1, pos_up1 - pos1, Math_PI, color, Rect2(uvx1 - 0.5f * dist, 0.f, dist, 1.f));
}
}