diff --git a/README.md b/README.md index 1fee5f2..5bba532 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ This is an extension project for the new Unity UI system which can be found at: [Unity UI Source](https://bitbucket.org/Unity-Technologies/ui) #For Unity 5.2.2+ - Use the new 5.3 package!# - +#*Note, due to limited demand, this is the last release we will update the 4.x/5.1 asset package, we'll be focusing on 5.3/5.4 from now on. ##Intro## For more info, here's a little introduction video for the project: @@ -15,7 +15,7 @@ For more info, here's a little introduction video for the project: In this repository is a collection of extension scripts to enhance your Unity UI experience. These scripts have been gathered from many sources and combined and improved over time. (The majority of the scripts came from the Scripts thread on the [Unity UI forum here](http://bit.ly/UnityUIScriptsForumPost)) -You can either download / fork the project to access the scripts, or you can download this precompiled Unity Asset, chock full of goodness +You can either download / fork the project to access the scripts, or you can also download this precompiled Unity Asset, chock full of goodness ### [Unity UI Extensions Unity 4.x Asset](https://bitbucket.org/ddreaper/unity-ui-extensions/downloads/UnityUIExtensions-4.x.unitypackage)### ### [Unity UI Extensions Unity 5.1 Asset](https://bitbucket.org/ddreaper/unity-ui-extensions/downloads/UnityUIExtensions-5.1.unitypackage)### ### [Unity UI Extensions Unity 5.2 Asset](https://bitbucket.org/ddreaper/unity-ui-extensions/downloads/UnityUIExtensions-5.2.unitypackage)### <- 5.2.0 - 5.2.1 base releases ONLY @@ -28,23 +28,13 @@ To get started with the project, here's a little guide: --- ## Updates: ## -###Update 1.0.4### +###Update 1.1.0### +Coming soon -[![View Getting Started Video](http://img.youtube.com/vi/oF48Qpaq3ls/0.jpg)](http://www.youtube.com/watch?v=oF48Qpaq3ls "Update 1.0.0.4 for the Unity UI Extensions Project") ---- -###Update 1.0.5### -Few minor fixes and a couple of additional scripts. Predominately created the new 5.3 branch to maintain the UI API changes from the 5.2.1 Patch releases. 5.3 package is 100% compatible with 5.2.1 Patch releases. +###Release History### -###Update 1.0.6### - -[![View Getting Started Video](http://img.youtube.com/vi/jpyFiRvSmbg/0.jpg)](http://www.youtube.com/watch?v=jpyFiRvSmbg "Update 1.0.6 for the Unity UI Extensions Project") - -* Added the awesome ReOrderable List control, plus some other minor bugfixes / changes. -* Added a new version of the Scroll Snap control as an alternative to the fixed versions. -* New set of controls including some shader enhanced solutions -* I've added a donate column to the lists. If you are getting great use out of a control, help out the dev who created it. Optional of course. Will update with links as I get them. - -**1.0.6.1 - Minor update to enhance soft alpha mask and add cylinder text plus a fix to letter spacing** +For the full release history, follow the below link to the full release notes page. +### [Release Notes](https://bitbucket.org/ddreaper/unity-ui-extensions/src/c9354eadf4b9287790eb636c21e4107760cd7b87/RELEASENOTES.md?at=develop_5.3)### --- ## Controls and extensions listed in this project are: ## diff --git a/RELEASENOTES.md b/RELEASENOTES.md new file mode 100644 index 0000000..d1bbfb6 --- /dev/null +++ b/RELEASENOTES.md @@ -0,0 +1,45 @@ +# Unity UI Extensions release notes # + +**1.0.6.1 - Minor update to enhance soft alpha mask and add cylinder text plus a fix to letter spacing** + +###Update 1.0.6### +[![View 1.0.6 update Video](http://img.youtube.com/vi/jpyFiRvSmbg/0.jpg)](http://www.youtube.com/watch?v=jpyFiRvSmbg "Update 1.0.6 for the Unity UI Extensions Project") + +* Added the awesome ReOrderable List control, plus some other minor bugfixes / changes. +* Added a new version of the Scroll Snap control as an alternative to the fixed versions. +* New set of controls including some shader enhanced solutions +* I've added a donate column to the lists. If you are getting great use out of a control, help out the dev who created it. Optional of course. Will update with links as I get them. + +###Update 1.0.5### +Few minor fixes and a couple of additional scripts. Predominately created the new 5.3 branch to maintain the UI API changes from the 5.2.1 Patch releases. 5.3 package is 100% compatible with 5.2.1 Patch releases. + +###Update 1.0.4### + +[![View Getting Started Video](http://img.youtube.com/vi/oF48Qpaq3ls/0.jpg)](http://www.youtube.com/watch?v=oF48Qpaq3ls "Update 1.0.0.4 for the Unity UI Extensions Project") +--- + + + +#Additional Info# +======================= +### How do I get set up? ### +Either clone / download this repository to your machine and then copy the scripts in, or use the pre-packaged .UnityPackage for your version of Unity and import it as a custom package in to your project. + +### Contribution guidelines ### +Got a script you want added, then just fork and submit a PR. All contributions accepted (including fixes) +Just ensure +* The header of the script matches the standard used in all scripts +* The script uses the **Unity.UI.Extensions** namespace so they do not affect any other developments +* (optional) Add Component and Editor options where possible (editor options are in the Editor\UIExtensionsMenuOptions.cs file) + +### License ### +All scripts conform to the BSD license and are free to use / distribute. See the [LICENSE](https://bitbucket.org/ddreaper/unity-ui-extensions/src/6d03f25b0150994afa97c6a55854d6ae696cad13/LICENSE?at=default) file for more information + +### Like what you see? ### +All these scripts were put together for my latest book Unity3D UI Essentials +Check out the [page on my blog](http://bit.ly/Unity3DUIEssentials) for more details and learn all about the inner workings of the new Unity UI System. + +### The downloads ### +As this repo was created to support my new Unity UI Title ["Unity 3D UI Essentials"](http://bit.ly/Unity3DUIEssentials), in the downloads section you will find two custom assets (SpaceShip-DemoScene-Start.unitypackage and RollABallSample-Start.unitypackage). These are just here as starter scenes for doing UI tasks in the book. + +I will add more sample scenes for the UI examples in this repository and detail them above over time. \ No newline at end of file diff --git a/RELEASENOTES.md.meta b/RELEASENOTES.md.meta new file mode 100644 index 0000000..71b2c05 --- /dev/null +++ b/RELEASENOTES.md.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 295bdc5c9df74e146bd5fa63aa5aeaf8 +timeCreated: 1463598733 +licenseType: Pro +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Scripts/Layout/HorizontalScrollSnap.cs b/Scripts/Layout/HorizontalScrollSnap.cs index 3ddb137..daf84d8 100644 --- a/Scripts/Layout/HorizontalScrollSnap.cs +++ b/Scripts/Layout/HorizontalScrollSnap.cs @@ -7,7 +7,7 @@ using UnityEngine.EventSystems; namespace UnityEngine.UI.Extensions { - + [RequireComponent(typeof(ScrollRect))] [AddComponentMenu("Layout/Extensions/Horizontal Scroll Snap")] public class HorizontalScrollSnap : MonoBehaviour, IBeginDragHandler, IEndDragHandler, IDragHandler @@ -41,13 +41,25 @@ namespace UnityEngine.UI.Extensions private bool _startDrag = true; private Vector3 _startPosition = new Vector3(); + + [Tooltip("The currently active page")] + [SerializeField] private int _currentScreen; [Tooltip("The screen / page to start the control on")] public int StartingScreen = 1; + [Tooltip("The distance between two pages, by default 3 times the height of the control")] public int PageStep = 0; + public int CurrentPage + { + get + { + return _currentScreen; + } + } + // Use this for initialization @@ -61,22 +73,10 @@ namespace UnityEngine.UI.Extensions } DistributePages(); - _screens = _screensContainer.childCount; - _lerp = false; + _currentScreen = StartingScreen; - _positions = new System.Collections.Generic.List(); - - if (_screens > 0) - { - for (float i = 0; i < _screens; ++i) - { - _scroll_rect.horizontalNormalizedPosition = i / (_screens - 1); - _positions.Add(_screensContainer.localPosition); - } - } - - _scroll_rect.horizontalNormalizedPosition = (float)(StartingScreen - 1) / (_screens - 1); + _scroll_rect.horizontalNormalizedPosition = (float)(_currentScreen - 1) / (_screens - 1); ChangeBulletsInfo(_currentScreen); @@ -221,6 +221,19 @@ namespace UnityEngine.UI.Extensions _dimension = currentXPosition + _offset * -1; _screensContainer.GetComponent().offsetMax = new Vector2(_dimension, 0f); + + _screens = _screensContainer.childCount; + + _positions = new System.Collections.Generic.List(); + + if (_screens > 0) + { + for (float i = 0; i < _screens; ++i) + { + _scroll_rect.horizontalNormalizedPosition = i / (_screens - 1); + _positions.Add(_screensContainer.localPosition); + } + } } int GetPageforPosition(Vector3 pos) @@ -247,13 +260,63 @@ namespace UnityEngine.UI.Extensions } } + /// + /// Add a new child to this Scroll Snap and recalculate it's children + /// + /// GameObject to add to the ScrollSnap + public void AddChild(GameObject GO) + { + _scroll_rect.horizontalNormalizedPosition = 0; + GO.transform.SetParent(_screensContainer); + DistributePages(); + + _scroll_rect.horizontalNormalizedPosition = (float)(_currentScreen) / (_screens - 1); + } + + /// + /// Remove a new child to this Scroll Snap and recalculate it's children + /// *Note, this is an index address (0-x) + /// + /// + /// + public void RemoveChild(int index, out GameObject ChildRemoved) + { + ChildRemoved = null; + if (index < 0 || index > _screensContainer.childCount) + { + return; + } + _scroll_rect.horizontalNormalizedPosition = 0; + var children = _screensContainer.transform; + int i = 0; + foreach (Transform child in children) + { + if (i == index) + { + child.SetParent(null); + ChildRemoved = child.gameObject; + break; + } + i++; + } + DistributePages(); + if (_currentScreen > _screens - 1) + { + _currentScreen = _screens - 1; + } + + _scroll_rect.horizontalNormalizedPosition = (float)(_currentScreen) / (_screens - 1); + } + + + #region Interfaces public void OnBeginDrag(PointerEventData eventData) { _startPosition = _screensContainer.localPosition; _fastSwipeCounter = 0; _fastSwipeTimer = true; - _currentScreen = CurrentScreen(); + _currentScreen = CurrentScreen(); } public void OnEndDrag(PointerEventData eventData) diff --git a/Scripts/Layout/VerticalScrollSnap.cs b/Scripts/Layout/VerticalScrollSnap.cs index 13e9161..27b9c9d 100644 --- a/Scripts/Layout/VerticalScrollSnap.cs +++ b/Scripts/Layout/VerticalScrollSnap.cs @@ -40,13 +40,25 @@ namespace UnityEngine.UI.Extensions private bool _startDrag = true; private Vector3 _startPosition = new Vector3(); + + [Tooltip("The currently active page")] + [SerializeField] private int _currentScreen; [Tooltip("The screen / page to start the control on")] public int StartingScreen = 1; + [Tooltip("The distance between two pages, by default 3 times the width of the control")] public int PageStep = 0; + public int CurrentPage + { + get + { + return _currentScreen; + } + } + // Use this for initialization void Start() { @@ -58,22 +70,10 @@ namespace UnityEngine.UI.Extensions } DistributePages(); - _screens = _screensContainer.childCount; - _lerp = false; + _currentScreen = StartingScreen; - _positions = new System.Collections.Generic.List(); - - if (_screens > 0) - { - for (int i = 0; i < _screens; ++i) - { - _scroll_rect.verticalNormalizedPosition = (float)i / (float)(_screens - 1); - _positions.Add(_screensContainer.localPosition); - } - } - - _scroll_rect.verticalNormalizedPosition = (float)(StartingScreen - 1) / (float)(_screens - 1); + _scroll_rect.verticalNormalizedPosition = (float)(_currentScreen - 1) / (float)(_screens - 1); ChangeBulletsInfo(_currentScreen); @@ -219,6 +219,19 @@ namespace UnityEngine.UI.Extensions _dimension = currentYPosition + _offset * -1; _screensContainer.GetComponent().offsetMax = new Vector2(0f,_dimension); + + _screens = _screensContainer.childCount; + + _positions = new System.Collections.Generic.List(); + + if (_screens > 0) + { + for (int i = 0; i < _screens; ++i) + { + _scroll_rect.verticalNormalizedPosition = (float)i / (float)(_screens - 1); + _positions.Add(_screensContainer.localPosition); + } + } } int GetPageforPosition(Vector3 pos) @@ -245,6 +258,54 @@ namespace UnityEngine.UI.Extensions } } + /// + /// Add a new child to this Scroll Snap and recalculate it's children + /// + /// GameObject to add to the ScrollSnap + public void AddChild(GameObject GO) + { + _scroll_rect.verticalNormalizedPosition = 0; + GO.transform.SetParent(_screensContainer); + DistributePages(); + + _scroll_rect.verticalNormalizedPosition = (float)(_currentScreen) / (_screens - 1); + } + + /// + /// Remove a new child to this Scroll Snap and recalculate it's children + /// *Note, this is an index address (0-x) + /// + /// + /// + public void RemoveChild(int index, out GameObject ChildRemoved) + { + ChildRemoved = null; + if (index < 0 || index > _screensContainer.childCount) + { + return; + } + _scroll_rect.verticalNormalizedPosition = 0; + var children = _screensContainer.transform; + int i = 0; + foreach (Transform child in children) + { + if (i == index) + { + child.SetParent(null); + ChildRemoved = child.gameObject; + break; + } + i++; + } + DistributePages(); + if (_currentScreen > _screens - 1) + { + _currentScreen = _screens - 1; + } + + _scroll_rect.verticalNormalizedPosition = (float)(_currentScreen) / (_screens - 1); + } + #region Interfaces public void OnBeginDrag(PointerEventData eventData) { diff --git a/Scripts/Primitives/UILineRenderer.cs b/Scripts/Primitives/UILineRenderer.cs index 4fffd8a..a4a6996 100644 --- a/Scripts/Primitives/UILineRenderer.cs +++ b/Scripts/Primitives/UILineRenderer.cs @@ -21,6 +21,13 @@ namespace UnityEngine.UI.Extensions Bevel, Miter } + public enum BezierType + { + None, + Quick, + Basic, + Improved, + } private const float MIN_MITER_JOIN = 15 * Mathf.Deg2Rad; @@ -58,6 +65,9 @@ namespace UnityEngine.UI.Extensions public bool LineCaps = false; public JoinType LineJoins = JoinType.Bevel; + public BezierType BezierMode = BezierType.None; + public int BezierSegmentsPerCurve = 10; + public override Texture mainTexture { get @@ -126,6 +136,29 @@ namespace UnityEngine.UI.Extensions { if (m_points == null) return; + Vector2[] pointsToDraw = m_points; + //If Bezier is desired, pick the implementation + if (BezierMode != BezierType.None && m_points.Length > 3) + { + BezierPath bezierPath = new BezierPath(); + + bezierPath.SetControlPoints(pointsToDraw); + bezierPath.SegmentsPerCurve = BezierSegmentsPerCurve; + List drawingPoints; + switch (BezierMode) + { + case BezierType.Basic: + drawingPoints = bezierPath.GetDrawingPoints0(); + break; + case BezierType.Improved: + drawingPoints = bezierPath.GetDrawingPoints1(); + break; + default: + drawingPoints = bezierPath.GetDrawingPoints2(); + break; + } + pointsToDraw = drawingPoints.ToArray(); + } var sizeX = rectTransform.rect.width; var sizeY = rectTransform.rect.height; @@ -153,10 +186,10 @@ namespace UnityEngine.UI.Extensions var segments = new List(); if (LineList) { - for (var i = 1; i < m_points.Length; i += 2) + for (var i = 1; i < pointsToDraw.Length; i += 2) { - var start = m_points[i - 1]; - var end = m_points[i]; + var start = pointsToDraw[i - 1]; + var end = pointsToDraw[i]; start = new Vector2(start.x * sizeX + offsetX, start.y * sizeY + offsetY); end = new Vector2(end.x * sizeX + offsetX, end.y * sizeY + offsetY); @@ -175,10 +208,10 @@ namespace UnityEngine.UI.Extensions } else { - for (var i = 1; i < m_points.Length; i++) + for (var i = 1; i < pointsToDraw.Length; i++) { - var start = m_points[i - 1]; - var end = m_points[i]; + var start = pointsToDraw[i - 1]; + var end = pointsToDraw[i]; start = new Vector2(start.x * sizeX + offsetX, start.y * sizeY + offsetY); end = new Vector2(end.x * sizeX + offsetX, end.y * sizeY + offsetY); @@ -189,7 +222,7 @@ namespace UnityEngine.UI.Extensions segments.Add(CreateLineSegment(start, end, SegmentType.Middle)); - if (LineCaps && i == m_points.Length - 1) + if (LineCaps && i == pointsToDraw.Length - 1) { segments.Add(CreateLineCap(start, end, SegmentType.End)); } diff --git a/Scripts/Utilities/BezierPath.cs b/Scripts/Utilities/BezierPath.cs new file mode 100644 index 0000000..03b8bde --- /dev/null +++ b/Scripts/Utilities/BezierPath.cs @@ -0,0 +1,350 @@ +/** + + This class demonstrates the code discussed in these two articles: + + http://devmag.org.za/2011/04/05/bzier-curves-a-tutorial/ + http://devmag.org.za/2011/06/23/bzier-path-algorithms/ + + Use this code as you wish, at your own risk. If it blows up + your computer, makes a plane crash, or otherwise cause damage, + injury, or death, it is not my fault. + + @author Herman Tulleken, dev.mag.org.za + +*/ + + +using System.Collections.Generic; + +namespace UnityEngine.UI.Extensions +{ + /** + Class for representing a Bezier path, and methods for getting suitable points to + draw the curve with line segments. +*/ + public class BezierPath + { + public int SegmentsPerCurve = 10; + public float MINIMUM_SQR_DISTANCE = 0.01f; + + // This corresponds to about 172 degrees, 8 degrees from a straight line + public float DIVISION_THRESHOLD = -0.99f; + + private List controlPoints; + + private int curveCount; //how many bezier curves in this path? + + /** + Constructs a new empty Bezier curve. Use one of these methods + to add points: SetControlPoints, Interpolate, SamplePoints. + */ + public BezierPath() + { + controlPoints = new List(); + } + + /** + Sets the control points of this Bezier path. + Points 0-3 forms the first Bezier curve, points + 3-6 forms the second curve, etc. + */ + public void SetControlPoints(List newControlPoints) + { + controlPoints.Clear(); + controlPoints.AddRange(newControlPoints); + curveCount = (controlPoints.Count - 1) / 3; + } + + public void SetControlPoints(Vector2[] newControlPoints) + { + controlPoints.Clear(); + controlPoints.AddRange(newControlPoints); + curveCount = (controlPoints.Count - 1) / 3; + } + + /** + Returns the control points for this Bezier curve. + */ + public List GetControlPoints() + { + return controlPoints; + } + + + /** + Calculates a Bezier interpolated path for the given points. + */ + public void Interpolate(List segmentPoints, float scale) + { + controlPoints.Clear(); + + if (segmentPoints.Count < 2) + { + return; + } + + for (int i = 0; i < segmentPoints.Count; i++) + { + if (i == 0) // is first + { + Vector2 p1 = segmentPoints[i]; + Vector2 p2 = segmentPoints[i + 1]; + + Vector2 tangent = (p2 - p1); + Vector2 q1 = p1 + scale * tangent; + + controlPoints.Add(p1); + controlPoints.Add(q1); + } + else if (i == segmentPoints.Count - 1) //last + { + Vector2 p0 = segmentPoints[i - 1]; + Vector2 p1 = segmentPoints[i]; + Vector2 tangent = (p1 - p0); + Vector2 q0 = p1 - scale * tangent; + + controlPoints.Add(q0); + controlPoints.Add(p1); + } + else + { + Vector2 p0 = segmentPoints[i - 1]; + Vector2 p1 = segmentPoints[i]; + Vector2 p2 = segmentPoints[i + 1]; + Vector2 tangent = (p2 - p0).normalized; + Vector2 q0 = p1 - scale * tangent * (p1 - p0).magnitude; + Vector2 q1 = p1 + scale * tangent * (p2 - p1).magnitude; + + controlPoints.Add(q0); + controlPoints.Add(p1); + controlPoints.Add(q1); + } + } + + curveCount = (controlPoints.Count - 1) / 3; + } + + /** + Sample the given points as a Bezier path. + */ + public void SamplePoints(List sourcePoints, float minSqrDistance, float maxSqrDistance, float scale) + { + if (sourcePoints.Count < 2) + { + return; + } + + Stack samplePoints = new Stack(); + + samplePoints.Push(sourcePoints[0]); + + Vector2 potentialSamplePoint = sourcePoints[1]; + + int i = 2; + + for (i = 2; i < sourcePoints.Count; i++) + { + if ( + ((potentialSamplePoint - sourcePoints[i]).sqrMagnitude > minSqrDistance) && + ((samplePoints.Peek() - sourcePoints[i]).sqrMagnitude > maxSqrDistance)) + { + samplePoints.Push(potentialSamplePoint); + } + + potentialSamplePoint = sourcePoints[i]; + } + + //now handle last bit of curve + Vector2 p1 = samplePoints.Pop(); //last sample point + Vector2 p0 = samplePoints.Peek(); //second last sample point + Vector2 tangent = (p0 - potentialSamplePoint).normalized; + float d2 = (potentialSamplePoint - p1).magnitude; + float d1 = (p1 - p0).magnitude; + p1 = p1 + tangent * ((d1 - d2) / 2); + + samplePoints.Push(p1); + samplePoints.Push(potentialSamplePoint); + + + Interpolate(new List(samplePoints), scale); + } + + /** + Caluclates a point on the path. + + @param curveIndex The index of the curve that the point is on. For example, + the second curve (index 1) is the curve with controlpoints 3, 4, 5, and 6. + + @param t The paramater indicating where on the curve the point is. 0 corresponds + to the "left" point, 1 corresponds to the "right" end point. + */ + public Vector2 CalculateBezierPoint(int curveIndex, float t) + { + int nodeIndex = curveIndex * 3; + + Vector2 p0 = controlPoints[nodeIndex]; + Vector2 p1 = controlPoints[nodeIndex + 1]; + Vector2 p2 = controlPoints[nodeIndex + 2]; + Vector2 p3 = controlPoints[nodeIndex + 3]; + + return CalculateBezierPoint(t, p0, p1, p2, p3); + } + + /** + Gets the drawing points. This implementation simply calculates a certain number + of points per curve. + */ + public List GetDrawingPoints0() + { + List drawingPoints = new List(); + + for (int curveIndex = 0; curveIndex < curveCount; curveIndex++) + { + if (curveIndex == 0) //Only do this for the first end point. + //When i != 0, this coincides with the + //end point of the previous segment, + { + drawingPoints.Add(CalculateBezierPoint(curveIndex, 0)); + } + + for (int j = 1; j <= SegmentsPerCurve; j++) + { + float t = j / (float)SegmentsPerCurve; + drawingPoints.Add(CalculateBezierPoint(curveIndex, t)); + } + } + + return drawingPoints; + } + + /** + Gets the drawing points. This implementation simply calculates a certain number + of points per curve. + + This is a lsightly different inplementation from the one above. + */ + public List GetDrawingPoints1() + { + List drawingPoints = new List(); + + for (int i = 0; i < controlPoints.Count - 3; i += 3) + { + Vector2 p0 = controlPoints[i]; + Vector2 p1 = controlPoints[i + 1]; + Vector2 p2 = controlPoints[i + 2]; + Vector2 p3 = controlPoints[i + 3]; + + if (i == 0) //only do this for the first end point. When i != 0, this coincides with the end point of the previous segment, + { + drawingPoints.Add(CalculateBezierPoint(0, p0, p1, p2, p3)); + } + + for (int j = 1; j <= SegmentsPerCurve; j++) + { + float t = j / (float)SegmentsPerCurve; + drawingPoints.Add(CalculateBezierPoint(t, p0, p1, p2, p3)); + } + } + + return drawingPoints; + } + + /** + This gets the drawing points of a bezier curve, using recursive division, + which results in less points for the same accuracy as the above implementation. + */ + public List GetDrawingPoints2() + { + List drawingPoints = new List(); + + for (int curveIndex = 0; curveIndex < curveCount; curveIndex++) + { + List bezierCurveDrawingPoints = FindDrawingPoints(curveIndex); + + if (curveIndex != 0) + { + //remove the fist point, as it coincides with the last point of the previous Bezier curve. + bezierCurveDrawingPoints.RemoveAt(0); + } + + drawingPoints.AddRange(bezierCurveDrawingPoints); + } + + return drawingPoints; + } + + List FindDrawingPoints(int curveIndex) + { + List pointList = new List(); + + Vector2 left = CalculateBezierPoint(curveIndex, 0); + Vector2 right = CalculateBezierPoint(curveIndex, 1); + + pointList.Add(left); + pointList.Add(right); + + FindDrawingPoints(curveIndex, 0, 1, pointList, 1); + + return pointList; + } + + + /** + @returns the number of points added. + */ + int FindDrawingPoints(int curveIndex, float t0, float t1, + List pointList, int insertionIndex) + { + Vector2 left = CalculateBezierPoint(curveIndex, t0); + Vector2 right = CalculateBezierPoint(curveIndex, t1); + + if ((left - right).sqrMagnitude < MINIMUM_SQR_DISTANCE) + { + return 0; + } + + float tMid = (t0 + t1) / 2; + Vector2 mid = CalculateBezierPoint(curveIndex, tMid); + + Vector2 leftDirection = (left - mid).normalized; + Vector2 rightDirection = (right - mid).normalized; + + if (Vector2.Dot(leftDirection, rightDirection) > DIVISION_THRESHOLD || Mathf.Abs(tMid - 0.5f) < 0.0001f) + { + int pointsAddedCount = 0; + + pointsAddedCount += FindDrawingPoints(curveIndex, t0, tMid, pointList, insertionIndex); + pointList.Insert(insertionIndex + pointsAddedCount, mid); + pointsAddedCount++; + pointsAddedCount += FindDrawingPoints(curveIndex, tMid, t1, pointList, insertionIndex + pointsAddedCount); + + return pointsAddedCount; + } + + return 0; + } + + + + /** + Caluclates a point on the Bezier curve represented with the four controlpoints given. + */ + private Vector2 CalculateBezierPoint(float t, Vector2 p0, Vector2 p1, Vector2 p2, Vector2 p3) + { + float u = 1 - t; + float tt = t * t; + float uu = u * u; + float uuu = uu * u; + float ttt = tt * t; + + Vector2 p = uuu * p0; //first term + + p += 3 * uu * t * p1; //second term + p += 3 * u * tt * p2; //third term + p += ttt * p3; //fourth term + + return p; + + } + } +} \ No newline at end of file diff --git a/Scripts/Utilities/BezierPath.cs.meta b/Scripts/Utilities/BezierPath.cs.meta new file mode 100644 index 0000000..e54a13b --- /dev/null +++ b/Scripts/Utilities/BezierPath.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 89b61e0416e1256469165fca78d5ed21 +timeCreated: 1463598733 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: