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