diff --git a/_DOTween.Assembly/DOTween/DOTween.csproj b/_DOTween.Assembly/DOTween/DOTween.csproj
index 3747ea3..d0c5db0 100644
--- a/_DOTween.Assembly/DOTween/DOTween.csproj
+++ b/_DOTween.Assembly/DOTween/DOTween.csproj
@@ -106,6 +106,7 @@
+
diff --git a/_DOTween.Assembly/DOTween/PathType.cs b/_DOTween.Assembly/DOTween/PathType.cs
index 965c11e..e7c711c 100644
--- a/_DOTween.Assembly/DOTween/PathType.cs
+++ b/_DOTween.Assembly/DOTween/PathType.cs
@@ -14,6 +14,8 @@ namespace DG.Tweening
/// Linear, composed of straight segments between each waypoint
Linear,
/// Curved path (which uses Catmull-Rom curves)
- CatmullRom
+ CatmullRom,
+// /// Curved path (which uses Cubic Bezier curves, where each point requires two extra control points)
+// CubicBezier // Under development
}
}
\ No newline at end of file
diff --git a/_DOTween.Assembly/DOTween/Plugins/Core/PathCore/CubicBezierDecoder.cs b/_DOTween.Assembly/DOTween/Plugins/Core/PathCore/CubicBezierDecoder.cs
new file mode 100644
index 0000000..371f87e
--- /dev/null
+++ b/_DOTween.Assembly/DOTween/Plugins/Core/PathCore/CubicBezierDecoder.cs
@@ -0,0 +1,141 @@
+// Author: Daniele Giardini - http://www.demigiant.com
+// Created: 2018/11/30 11:58
+// License Copyright (c) Daniele Giardini
+// This work is subject to the terms at http://dotween.demigiant.com/license.php
+
+using System;
+using UnityEngine;
+
+namespace DG.Tweening.Plugins.Core.PathCore
+{
+ internal class CubicBezierDecoder : ABSPathDecoder
+ {
+ // wps must be in multiple of 3 (each waypoint has 2 control points), in this order:
+ // - waypoint
+ // - IN control point
+ // - OUT control point
+ internal override void FinalizePath(Path p, Vector3[] wps, bool isClosedPath)
+ {
+ int wpsLen = wps.Length;
+ if (wpsLen < 6 || wpsLen % 3 != 0) {
+ Debug.LogError("CubicBezier paths must contain waypoints in multiple of 3 (1: waypoint, 2: IN control point, 3: OUT control point)");
+ return;
+ }
+
+ int wpsOnlyLen = wpsLen / 3;
+ // Store control points
+ p.controlPoints = new ControlPoint[wpsOnlyLen];
+ int cpIndex = 0;
+ for (int i = 0; i < wpsLen; i+=3) {
+ p.controlPoints[cpIndex] = new ControlPoint(wps[i+1], wps[i+2]);
+ cpIndex++;
+ }
+ // Manage closed path
+ if (isClosedPath) {
+ // TODO Bezier Closed Path
+ }
+ // Store total subdivisions
+ p.subdivisions = wpsOnlyLen * p.subdivisionsXSegment;
+ // Store time to len tables
+ SetTimeToLengthTables(p, p.subdivisions);
+ // Store waypoints lengths
+ SetWaypointsLengths(p, p.subdivisionsXSegment);
+
+
+// // Add starting and ending control points (uses only one vector per control point)
+// wpsLen = wps.Length;
+// if (p.controlPoints == null || p.controlPoints.Length != 2) p.controlPoints = new ControlPoint[2];
+// if (isClosedPath) {
+// p.controlPoints[0] = new ControlPoint(wps[wpsLen - 2], Vector3.zero);
+// p.controlPoints[1] = new ControlPoint(wps[1], Vector3.zero);
+// } else {
+// p.controlPoints[0] = new ControlPoint(wps[1], Vector3.zero);
+// Vector3 lastP = wps[wpsLen - 1];
+// Vector3 diffV = lastP - wps[wpsLen - 2];
+// p.controlPoints[1] = new ControlPoint(lastP + diffV, Vector3.zero);
+// }
+// // Store total subdivisions
+// p.subdivisions = wpsLen * p.subdivisionsXSegment;
+// // Store time to len tables
+// SetTimeToLengthTables(p, p.subdivisions);
+// // Store waypoints lengths
+// SetWaypointsLengths(p, p.subdivisionsXSegment);
+ }
+
+ // controlPoints as a separate parameter so we can pass custom ones from SetWaypointsLengths
+ internal override Vector3 GetPoint(float perc, Vector3[] wps, Path p, ControlPoint[] controlPoints)
+ {
+ int numSections = wps.Length - 1; // Considering also control points
+ int tSec = (int)Math.Floor(perc * numSections);
+ int currPt = numSections - 1;
+ if (currPt > tSec) currPt = tSec;
+ float u = perc * numSections - currPt;
+
+ Vector3 a = currPt == 0 ? controlPoints[0].a : wps[currPt - 1];
+ Vector3 b = wps[currPt];
+ Vector3 c = wps[currPt + 1];
+ Vector3 d = currPt + 2 > wps.Length - 1 ? controlPoints[1].a : wps[currPt + 2];
+
+ return .5f * (
+ (-a + 3f * b - 3f * c + d) * (u * u * u)
+ + (2f * a - 5f * b + 4f * c - d) * (u * u)
+ + (-a + c) * u
+ + 2f * b
+ );
+ }
+
+ internal void SetTimeToLengthTables(Path p, int subdivisions)
+ {
+ float pathLen = 0;
+ float incr = 1f / subdivisions;
+ float[] timesTable = new float[subdivisions];
+ float[] lengthsTable = new float[subdivisions];
+ Vector3 prevP = GetPoint(0, p.wps, p, p.controlPoints);
+ for (int i = 1; i < subdivisions + 1; ++i) {
+ float perc = incr * i;
+ Vector3 currP = GetPoint(perc, p.wps, p, p.controlPoints);
+ pathLen += Vector3.Distance(currP, prevP);
+ prevP = currP;
+ timesTable[i - 1] = perc;
+ lengthsTable[i - 1] = pathLen;
+ }
+
+ // Assign
+ p.length = pathLen;
+ p.timesTable = timesTable;
+ p.lengthsTable = lengthsTable;
+ }
+
+ internal void SetWaypointsLengths(Path p, int subdivisions)
+ {
+ // Create a relative path between each waypoint,
+ // with its start and end control lines coinciding with the next/prev waypoints.
+ int count = p.wps.Length;
+ float[] wpLengths = new float[count];
+ wpLengths[0] = 0;
+ ControlPoint[] partialControlPs = new ControlPoint[2];
+ Vector3[] partialWps = new Vector3[2];
+ for (int i = 1; i < count; ++i) {
+ // Create partial path
+ partialControlPs[0].a = i == 1 ? p.controlPoints[0].a : p.wps[i - 2];
+ partialWps[0] = p.wps[i - 1];
+ partialWps[1] = p.wps[i];
+ partialControlPs[1].a = i == count - 1 ? p.controlPoints[1].a : p.wps[i + 1];
+ // Calculate length of partial path
+ float partialLen = 0;
+ float incr = 1f / subdivisions;
+ Vector3 prevP = GetPoint(0, partialWps, p, partialControlPs);
+ for (int c = 1; c < subdivisions + 1; ++c) {
+ float perc = incr * c;
+ Vector3 currP = GetPoint(perc, partialWps, p, partialControlPs);
+ partialLen += Vector3.Distance(currP, prevP);
+ prevP = currP;
+ }
+ wpLengths[i] = partialLen;
+ }
+
+ // Assign
+ p.wpLengths = wpLengths;
+ }
+ }
+}
\ No newline at end of file