daily pastebin goal
42%
SHARE
TWEET

Lines.cs

mvaganov Jul 15th, 2014 (edited) 388 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. using UnityEngine;
  2. using System.Collections.Generic;
  3.  
  4. // author: mvaganov@hotmail.com
  5. // license: Copyfree, public domain. This is free code! Great artists, steal this code!
  6. // latest version at: https://pastebin.com/8m69iTut -- added: WriteArcOnSphere (2017/10/25)
  7. public class Lines : MonoBehaviour {
  8.     [Tooltip("Used to draw lines. Ideally a white Self-Illumin/Diffuse shader. Or Default-Line")]
  9.     public Material lineMaterial;
  10.     public bool autoParentLinesToGlobalObject = true;
  11.  
  12.     /// <summary>The singleton instance.</summary>
  13.     static Lines instance;
  14.     public static Lines Instance() {
  15.         if(instance == null) {
  16.             if((instance = FindObjectOfType(typeof(Lines)) as Lines) == null) {
  17.                 GameObject g = new GameObject("<" + typeof(Lines).Name + ">");
  18.                 instance = g.AddComponent<Lines>();
  19.             }
  20.         }
  21.         return instance;
  22.     }
  23.  
  24.     /// <summary>
  25.     /// Make the specified Line.
  26.     /// example usage:
  27.     /// <para><code>
  28.     /// /* GameObject forwardLine should be a member variable */
  29.     /// Lines.Make (ref forwardLine, transform.position,
  30.     ///             transform.position + transform.forward, Color.blue, 0.1f, 0);
  31.     /// //This makes a long thin triangle, pointing forward.
  32.     /// </code></para>
  33.     /// </summary>
  34.     /// <param name="lineObject">GameObject host of the LineRenderer</param>
  35.     /// <param name="start">Start, an absolute world-space coordinate</param>
  36.     /// <param name="end">End, an absolute world-space coordinate</param>
  37.     /// <param name="startSize">How wide the line is at the start</param>
  38.     /// <param name="endSize">How wide the line is at the end</param>
  39.     public static LineRenderer Make(ref GameObject lineObject, Vector3 start, Vector3 end,
  40.         Color color = default(Color), float startSize = 0.125f, float endSize = 0.125f) {
  41.         if (lineObject == null) { lineObject = new GameObject(); }
  42.         if (Instance().autoParentLinesToGlobalObject) { lineObject.transform.SetParent (instance.transform); }
  43.         LineRenderer lr = lineObject.GetComponent<LineRenderer>();
  44.         if(lr == null) { lr = lineObject.AddComponent<LineRenderer>(); }
  45.         lr.startWidth = startSize;
  46.         lr.endWidth = endSize;
  47.         lr.positionCount = 2;
  48.         lr.SetPosition(0, start); lr.SetPosition(1, end);
  49.         SetColor(lr, color);
  50.         return lr;
  51.     }
  52.  
  53.     /// <summary>Make the specified Line from a list of points</summary>
  54.     /// <returns>The LineRenderer hosting the line</returns>
  55.     /// <param name="lineObject">GameObject host of the LineRenderer</param>
  56.     /// <param name="color">Color of the line</param>
  57.     /// <param name="points">List of absolute world-space coordinates</param>
  58.     /// <param name="pointCount">Number of the points used points list</param>
  59.     /// <param name="startSize">How wide the line is at the start</param>
  60.     /// <param name="endSize">How wide the line is at the end</param>
  61.     public static LineRenderer Make(ref GameObject lineObject, Vector3[] points, int pointCount,
  62.         Color color = default(Color), float startSize = 0.125f, float endSize = 0.125f) {
  63.         if (lineObject == null) { lineObject = new GameObject(); }
  64.         if (Instance().autoParentLinesToGlobalObject) { lineObject.transform.SetParent (instance.transform); }
  65.         LineRenderer lr = lineObject.GetComponent<LineRenderer>();
  66.         if(lr == null) { lr = lineObject.AddComponent<LineRenderer>(); }
  67.         lr.startWidth = startSize;
  68.         lr.endWidth = endSize;
  69.         lr.positionCount = pointCount;
  70.         for(int i = 0; i < pointCount; ++i) { lr.SetPosition(i, points[i]); }
  71.         SetColor(lr, color);
  72.         return lr;
  73.     }
  74.  
  75.     public static Material FindShaderMaterial(string shadername){
  76.         Shader s = Shader.Find(shadername);
  77.         if(s == null) {
  78.             throw new System.Exception("Missing shader: " + shadername
  79.                 + ". Please make sure it is in the \"Resources\" folder, "
  80.                 + "or used by at least one other object. Or, create an "
  81.                 + " object with Lines, and assign the material manually");
  82.         }
  83.         return new Material(s);
  84.     }
  85.  
  86.     public static void SetColor(LineRenderer lr, Color color) {
  87.         Material mat = Instance().lineMaterial;
  88.         if(mat == null) {
  89.             const string colorShaderName = "Sprites/Default";//"Unlit/Color";
  90.             mat = FindShaderMaterial(colorShaderName);
  91.             Instance ().lineMaterial = mat;
  92.         }
  93.         if(lr.material == null || lr.material.name != mat.name) { lr.material = mat; }
  94.         lr.material.color = color;
  95.     }
  96.  
  97.     /// <summary>Write 2D arc in 3D space, into given Vector3 array</summary>
  98.     /// <param name="points">Will host the list of coordinates</param>
  99.     /// <param name="pointCount">How many vertices to make &gt; 1</param>
  100.     /// <param name="normal">The surface-normal of the arc's plane</param>
  101.     /// <param name="firstPoint">Arc start, rotate about Vector3.zero</param>
  102.     /// <param name="angle">2D angle. Tip: Vector3.Angle(v1, v2)</param>
  103.     /// <param name="offset">How to translate the arc</param>
  104.     public static void WriteArc(ref Vector3[] points, int pointCount,
  105.         Vector3 normal, Vector3 firstPoint, float angle = 360, Vector3 offset = default(Vector3), int startIndex = 0) {
  106.         if(points == null) { points = new Vector3[pointCount]; }
  107.         points[startIndex] = firstPoint;
  108.         Quaternion q = Quaternion.AngleAxis(angle / (pointCount - 1), normal);
  109.         for(int i = startIndex+1; i < startIndex+pointCount; ++i) { points[i] = q * points[i - 1]; }
  110.         if(offset != Vector3.zero)
  111.             for(int i = startIndex; i < startIndex+pointCount; ++i) { points[i] += offset; }
  112.     }
  113.  
  114.     /// <summary>
  115.     /// Make the specified arc line in 3D space. Example usage: <para><code>
  116.     /// /* GameObject turnArc should be a member variable */
  117.     /// Lines.MakeArc(ref turnArc, Vector3.Angle(transform.forward, direction),
  118.     ///     10, Vector3.Cross(transform.forward, direction),
  119.     ///     transform.forward, transform.position, Color.green, 0.1f, 0);
  120.     /// // makes a curve showing the turn from transform.forward to direction
  121.     /// </code></para>
  122.     /// </summary>
  123.     /// <returns>The LineRenderer hosting the line</returns>
  124.     /// <param name="lineObject">GameObject host of the LineRenderer</param>
  125.     /// <param name="color">Color of the line</param>
  126.     /// <param name="center">Center of arc</param>
  127.     /// <param name="normal">surface-normal of arc's plane</param>
  128.     /// <param name="firstPoint">Arc start, rotate about Vector3.zero</param>
  129.     /// <param name="angle">2D angle. Tip: Vector3.Angle(v1, v2)</param>
  130.     /// <param name="pointCount">How many vertices to make &gt; 1</param>
  131.     /// <param name="startSize">How wide the line is at the start</param>
  132.     /// <param name="endSize">How wide the line is at the end</param>
  133.     public static LineRenderer MakeArc(ref GameObject lineObj,
  134.         float angle, int pointCount, Vector3 normal, Vector3 firstPoint,
  135.         Vector3 center = default(Vector3), Color color = default(Color), float startSize = 0.125f, float endSize = 0.125f) {
  136.         Vector3[] points = null;
  137.         WriteArc(ref points, pointCount, normal, firstPoint, angle, center);
  138.         return Make(ref lineObj, points, pointCount, color, startSize, endSize);
  139.     }
  140.  
  141.     public static LineRenderer MakeLineOnSphere(ref GameObject lineObj, Vector3 sphereCenter, Vector3 start, Vector3 end,
  142.     Color color=default(Color), float startSize=0.125f, float endSize=0.125f, int pointCount = 24) {
  143.         Vector3[] points = null;
  144.         WriteArcOnSphere(ref points, pointCount, sphereCenter, start, end);
  145.         return Make(ref lineObj, points, pointCount, color, startSize, endSize);
  146.     }
  147.     public static void WriteArcOnSphere(ref Vector3[] points, int pointCount, Vector3 sphereCenter, Vector3 start, Vector3 end) {
  148.         Vector3 axis;
  149.         if(start == -end) {
  150.             axis = (start != Vector3.up && end != Vector3.up)? Vector3.up : Vector3.right;
  151.         } else {
  152.             axis = Vector3.Cross(start, end).normalized;
  153.         }
  154.         Vector3 a = start - sphereCenter, b = end - sphereCenter;
  155.         float arad = a.magnitude, brad = b.magnitude;
  156.         a /= arad; b /= brad;
  157.         float angle = Vector3.Angle(a,b);
  158.         WriteArc(ref points, pointCount, axis, a, angle, Vector3.zero);
  159.         float raddelta = brad-arad;
  160.         for(int i=0; i < points.Length; ++i) {
  161.             points[i] = points[i] * ((i * raddelta / points.Length) + arad);
  162.             points[i] += sphereCenter;
  163.         }
  164.     }
  165.  
  166.     /// <summary>Makes a circle with a 3D line</summary>
  167.     /// <returns>The LineRenderer hosting the line</returns>
  168.     /// <param name="lineObj">GameObject host of the LineRenderer</param>
  169.     /// <param name="color">Color of the line</param>
  170.     /// <param name="center">Absolute world-space 3D coordinate</param>
  171.     /// <param name="normal">Which way the circle is facing</param>
  172.     /// <param name="radius"></param>
  173.     /// <param name="linesize">The width of the line</param>
  174.     public static LineRenderer MakeCircle(ref GameObject lineObj,
  175.         Vector3 center, Vector3 normal, Color color = default(Color), float radius = 1, float linesize = 0.125f) {
  176.         Vector3 crossDir = (normal != Vector3.up) ? Vector3.up : Vector3.forward;
  177.         Vector3 r = Vector3.Cross(normal, crossDir).normalized;
  178.         LineRenderer lr = Lines.MakeArc(ref lineObj, 360, 24, normal, r * radius, center, color,
  179.             linesize, linesize);
  180.         lr.loop = true;
  181.         return lr;
  182.     }
  183.     /// <summary>As MakeCircle, but using an assured GameObject</summary>
  184.     public static LineRenderer MakeCircle_With(GameObject lineObj,
  185.         Vector3 center, Vector3 normal, Color color = default(Color), float radius = 1, float linesize = 0.125f) {
  186.         return MakeCircle (ref lineObj, center, normal, color, radius, linesize);
  187.     }
  188.  
  189.     /// <returns>a line renderer in the shape of a sphere made of 3 circles, for the x.y.z axis</returns>
  190.     /// <param name="lineObj">Line object.</param>
  191.     /// <param name="radius">Radius.</param>
  192.     /// <param name="center">Center.</param>
  193.     /// <param name="color">Color.</param>
  194.     /// <param name="linesize">Linesize.</param>
  195.     public static LineRenderer MakeSphere(ref GameObject lineObj, float radius = 1,
  196.         Vector3 center = default(Vector3), Color color = default(Color), float linesize = 0.125f) {
  197.         Vector3[] circles = new Vector3[24 * 3];
  198.         Lines.WriteArc (ref circles, 24, Vector3.forward, Vector3.up, 360, center, 24*0);
  199.         Lines.WriteArc (ref circles, 24, Vector3.right,   Vector3.up, 360, center, 24*1);
  200.         Lines.WriteArc (ref circles, 24, Vector3.up, Vector3.forward, 360, center, 24*2);
  201.         if (radius != 1) { for (int i = 0; i < circles.Length; ++i) { circles [i] *= radius; } }
  202.         return Lines.Make (ref lineObj, circles, circles.Length, color, linesize, linesize);
  203.     }
  204.  
  205.     private static Vector3[] thumbtack_points_base = null;
  206.     /// <summary>Draws a "thumbtack", which shows a visualization for direction and orientation</summary>
  207.     /// <returns>The LineRenderer hosting the thumbtack line. The LineRenderer's transform can be adjusted!</returns>
  208.     /// <param name="lineObj">Line object.</param>
  209.     /// <param name="c">C: color</param>
  210.     /// <param name="size">Size: radius of the thumbtack</param>
  211.     /// <param name="lineWidth">Line width.</param>
  212.     public static LineRenderer MakeThumbtack(ref GameObject lineObj, Color c = default(Color), float size = 1, float lineWidth = 0.1f) {
  213.         const float epsilon = 1/1024.0f;
  214.         if(thumbtack_points_base == null) {
  215.             Vector3 pstn = Vector3.zero, fwrd = Vector3.forward * size, rght = Vector3.right * size, up__ = Vector3.up;
  216.             float startAngle = (360.0f / 4) - (360.0f / 32);
  217.             Vector3 v = Quaternion.AngleAxis(startAngle, up__) * fwrd;
  218.             Lines.WriteArc(ref thumbtack_points_base, 32, up__, v, 360, pstn);
  219.             Vector3 tip = pstn + fwrd * Mathf.Sqrt(2);
  220.             thumbtack_points_base[0] = thumbtack_points_base[thumbtack_points_base.Length - 1];
  221.             int m = (32 * 5 / 8) + 1;
  222.             thumbtack_points_base[m++] = thumbtack_points_base[m] + (tip - thumbtack_points_base[m]) * (1 - epsilon);
  223.             thumbtack_points_base[m++] = tip;
  224.             int n = (32 * 7 / 8) + 1;
  225.             while(n < 32) { thumbtack_points_base[m++] = thumbtack_points_base[n++]; }
  226.             Vector3 side = pstn + rght;
  227.             thumbtack_points_base[m++] = thumbtack_points_base[m] + (side - thumbtack_points_base[m]) * (1 - epsilon);
  228.             thumbtack_points_base[m++] = pstn + rght;
  229.             thumbtack_points_base[m++] = pstn + rght * epsilon;
  230.             thumbtack_points_base[m++] = pstn;
  231.             thumbtack_points_base[m++] = pstn + up__ * size * (1 - epsilon);
  232.             thumbtack_points_base[m++] = pstn + up__ * size;
  233.         }
  234.         LineRenderer lr = Lines.Make(ref lineObj, thumbtack_points_base, thumbtack_points_base.Length, c, lineWidth, lineWidth);
  235.         lr.useWorldSpace = false;
  236.         return lr;
  237.     }
  238.  
  239.     /// <summary>Draws a "thumbtack", which shows a visualization for direction and orientation</summary>
  240.     /// <returns>The LineRenderer hosting the thumbtack line</returns>
  241.     /// <param name="lineObj">Line object.</param>
  242.     /// <param name="t">t: the transform to attach the thumbtack visualisation to</param>
  243.     /// <param name="c">C: color</param>
  244.     /// <param name="size">Size: radius of the thumbtack</param>
  245.     /// <param name="lineWidth">Line width.</param>
  246.     public static LineRenderer SetThumbtack(ref GameObject lineObj, Transform t, Color c = default(Color), float size = 1, float lineWidth = 0.125f) {
  247.         LineRenderer line_ = MakeThumbtack (ref lineObj, c, size, lineWidth);
  248.         line_.transform.SetParent (t);
  249.         line_.transform.localPosition = Vector3.zero;
  250.         line_.transform.localRotation = Quaternion.identity;
  251.         return line_;
  252.     }
  253.  
  254.     public static Vector3 GetForwardVector(Quaternion q) {
  255.         return new Vector3 (2 * (q.x * q.z + q.w * q.y),
  256.             2 * (q.y * q.z + q.w * q.x),
  257.             1-2*(q.x * q.x + q.y * q.y));
  258.     }
  259.     public static Vector3 GetUpVector(Quaternion q) {
  260.         return new Vector3 (2 * (q.x * q.y + q.w * q.z),
  261.             1-2*(q.x * q.x + q.z * q.z),
  262.             2 * (q.y * q.z + q.w * q.x));
  263.     }
  264.     public static Vector3 GetRightVector(Quaternion q) {
  265.         return new Vector3 (1-2*(q.y * q.y + q.z * q.z),
  266.             2 * (q.x * q.y + q.w * q.z),
  267.             2 * (q.x * q.z + q.w * q.y));
  268.     }
  269.  
  270.     /// <example>CreateSpiralSphere(transform.position, 0.5f, transform.up, transform.forward, 16, 8);</example>
  271.     /// <summary>creates a line spiraled onto a sphere</summary>
  272.     /// <param name="center"></param>
  273.     /// <param name="radius"></param>
  274.     /// <param name="axis">example: Vector3.up</param>
  275.     /// <param name="axisFace">example: Vector3.right</param>
  276.     /// <param name="sides"></param>
  277.     /// <param name="rotations"></param>
  278.     /// <returns></returns>
  279.     public static Vector3[] CreateSpiralSphere(Vector3 center = default(Vector3), float radius = 1,
  280.         Vector3 axis = default(Vector3), Vector3 axisFace = default(Vector3), float sides = 12, float rotations = 6) {
  281.         List<Vector3> points = new List<Vector3>(); // List instead of Array because sides and rotations are floats!
  282.         if(axis == Vector3.zero) { axis=Vector3.up; }
  283.         if(axisFace == Vector3.zero) { axisFace=Vector3.right; }
  284.         if (sides != 0 && rotations != 0) {
  285.             float iter = 0;
  286.             float increment = 1f / (rotations * sides);
  287.             points.Add(center + axis * radius);
  288.             do {
  289.                 iter += increment;
  290.                 Quaternion faceTurn = Quaternion.AngleAxis(iter * 360 * rotations, axis);
  291.                 Vector3 newFace = faceTurn * axisFace;
  292.                 Quaternion q = Quaternion.LookRotation(newFace);
  293.                 Vector3 right = GetUpVector(q);
  294.                 Vector3 r = right * radius;
  295.                 q = Quaternion.AngleAxis(iter * 180, newFace);
  296.                 Vector3 newPoint = center + q * r;
  297.                 points.Add(newPoint);
  298.             }
  299.             while (iter < 1);
  300.         }
  301.         return points.ToArray();
  302.     }
  303.  
  304.     /// <returns>a line renderer in the shape of a spiraling sphere, spiraling about the Vector3.up axis</returns>
  305.     /// <param name="lineObj">Line object.</param>
  306.     /// <param name="radius">Radius.</param>
  307.     /// <param name="center">Center.</param>
  308.     /// <param name="color">Color.</param>
  309.     /// <param name="linesize">Linesize.</param>
  310.     public static LineRenderer MakeSpiralSphere(ref GameObject lineObj, float radius = 1,
  311.         Vector3 center = default(Vector3), Color color = default(Color), float linesize = 0.125f) {
  312.         Vector3[] verts = CreateSpiralSphere (center, radius, Vector3.up, Vector3.right, 24, 3);
  313.         return Make (ref lineObj, verts, verts.Length, color, linesize, linesize);
  314.     }
  315.  
  316.     public static LineRenderer MakeArrow(ref GameObject lineObject, Vector3 start, Vector3 end,
  317.         float arrowHeadSize = 4, Color color = default(Color), float startSize = 0.125f, float endSize = 0.125f) {
  318.         return MakeArrow(ref lineObject, new Vector3[] { start, end }, 2, arrowHeadSize, color, startSize, endSize);
  319.     }
  320.     public static LineRenderer MakeArrowBothEnds(ref GameObject lineObject, Vector3 start, Vector3 end,
  321.         float arrowHeadSize = 4, Color color = default(Color), float startSize = 0.125f, float endSize = 0.125f) {
  322.         return MakeArrowBothEnds(ref lineObject, new Vector3[] { start, end }, 2, arrowHeadSize, color, startSize, endSize);
  323.     }
  324.     public static LineRenderer MakeArrow(ref GameObject lineObject, Vector3[] points, int pointCount,
  325.         float arrowHeadSize = 4, Color color = default(Color), float startSize = 0.125f, float endSize = 0.125f, Keyframe[] lineKeyFrames = null) {
  326.         float arrowSize = endSize*arrowHeadSize;
  327.         int lastGoodIndex = 0;
  328.         Vector3 arrowheadBase = Vector3.zero, arrowheadWidest = Vector3.zero, delta, dir = Vector3.zero;
  329.         float dist = 0, backtracked = 0, extraFromLastGoodIndex = 0;
  330.         for(int i = points.Length-1; i>0; --i) {
  331.             float d = Vector3.Distance(points[i], points[i-1]);
  332.             dist += d;
  333.             backtracked += d;
  334.             if(backtracked >= arrowSize && dir == Vector3.zero) {
  335.                 lastGoodIndex = i-1;
  336.                 delta = points[i] - points[i-1];
  337.                 dir = delta.normalized;
  338.                 extraFromLastGoodIndex = backtracked - arrowSize;
  339.                 arrowheadBase = points[lastGoodIndex] + dir * extraFromLastGoodIndex;
  340.             }
  341.         }
  342.         if(dist <= arrowSize) { return Make(ref lineObject, points[0], points[points.Length-1], color, arrowSize, 0); }
  343.         delta = points[points.Length-1] - arrowheadBase;
  344.         dir = delta.normalized;
  345.         const float factionalArrowheadExpanseDelta = 1.0f/512;
  346.         arrowheadWidest = arrowheadBase + dir * (dist*factionalArrowheadExpanseDelta);
  347.         Vector3[] line = new Vector3[lastGoodIndex+4];
  348.         for(int i = 0; i<=lastGoodIndex; i++) {
  349.             line[i] = points[i];
  350.         }
  351.         line[lastGoodIndex+3] = points[points.Length-1];
  352.         line[lastGoodIndex+2] = arrowheadWidest;
  353.         line[lastGoodIndex+1] = arrowheadBase;
  354.         LineRenderer lr;
  355.         Keyframe[] keyframes;
  356.         float arrowHeadBaseStart = 1 - arrowSize/dist;
  357.         float arrowHeadBaseWidest = 1 - (arrowSize/dist-factionalArrowheadExpanseDelta);
  358.         if(lineKeyFrames == null) {
  359.             keyframes= new Keyframe[] {
  360.                 new Keyframe(0, startSize), new Keyframe(arrowHeadBaseStart, endSize),
  361.                 new Keyframe(arrowHeadBaseWidest, arrowSize), new Keyframe(1, 0)
  362.             };
  363.         } else {
  364.             // count how many there are after arrowHeadBaseStart.
  365.             float t = 0;
  366.             int validCount = lineKeyFrames.Length;
  367.             for(int i = 0; i < lineKeyFrames.Length; ++i) {
  368.                 t = lineKeyFrames[i].time;
  369.                 if(t > arrowHeadBaseStart) { validCount = i; break; }
  370.             }
  371.             // those are irrelivant now. they'll be replaced by the 3 extra points
  372.             keyframes = new Keyframe[validCount+3];
  373.             for(int i=0;i<validCount; ++i) { keyframes[i] = lineKeyFrames[i]; }
  374.             keyframes[validCount+0] = new Keyframe(arrowHeadBaseStart, endSize);
  375.             keyframes[validCount+1] = new Keyframe(arrowHeadBaseWidest, arrowSize);
  376.             keyframes[validCount+2] = new Keyframe(1, 0);
  377.         }
  378.         lr = Make(ref lineObject, line, line.Length, color, startSize, endSize);
  379.         lr.widthCurve = new AnimationCurve(keyframes);
  380.         return lr;
  381.     }
  382.     public static LineRenderer MakeArrowBothEnds(ref GameObject lineObject, Vector3[] points, int pointCount,
  383.         float arrowHeadSize = 4, Color color = default(Color), float startSize = 0.125f, float endSize = 0.125f) {
  384.         LineRenderer lr = MakeArrow(ref lineObject, points, pointCount, arrowHeadSize, color, startSize, endSize, null);
  385.         ReverseLineInternal(ref lr);
  386.         Vector3[] p = new Vector3[lr.positionCount];
  387.         lr.GetPositions(p);
  388.         lr = MakeArrow(ref lineObject, p, p.Length, arrowHeadSize, color, endSize, startSize, lr.widthCurve.keys);
  389.         ReverseLineInternal(ref lr);
  390.         return lr;
  391.     }
  392.     public static LineRenderer ReverseLineInternal(ref LineRenderer lr) {
  393.         Vector3[] p = new Vector3[lr.positionCount];
  394.         lr.GetPositions(p);
  395.         System.Array.Reverse(p);
  396.         lr.SetPositions(p);
  397.         if(lr.widthCurve != null && lr.widthCurve.length > 1) {
  398.             Keyframe[] kf = new Keyframe[lr.widthCurve.keys.Length];
  399.             Keyframe[] okf = lr.widthCurve.keys;
  400.             for(int i = 0; i<kf.Length; ++i) { kf[i]=okf[i]; }
  401.             System.Array.Reverse(kf);
  402.             for(int i = 0; i<kf.Length; ++i) { kf[i].time = 1-kf[i].time; }
  403.             lr.widthCurve = new AnimationCurve(kf);
  404.         }
  405.         return lr;
  406.     }
  407.  
  408.     public static LineRenderer MakeArcArrow(ref GameObject lineObj,
  409.         float angle, int pointCount, float arrowHeadSize = 4, Vector3 normal = default(Vector3), Vector3 firstPoint = default(Vector3),
  410.         Vector3 center = default(Vector3), Color color = default(Color), float startSize = 0.125f, float endSize = 0.125f) {
  411.         if(normal == default(Vector3)) { normal = Vector3.up; }
  412.         if(center == default(Vector3) && firstPoint == default(Vector3)) { firstPoint = Vector3.right; }
  413.         Vector3[] points = null;
  414.         WriteArc(ref points, pointCount, normal, firstPoint, angle, center);
  415.         return MakeArrow(ref lineObj, points, pointCount, arrowHeadSize, color, startSize, endSize);
  416.     }
  417.  
  418.     public static LineRenderer MakeArcArrowBothEnds(ref GameObject lineObj,
  419.         float angle, int pointCount, float arrowHeadSize = 4, Vector3 normal = default(Vector3), Vector3 firstPoint = default(Vector3),
  420.         Vector3 center = default(Vector3), Color color = default(Color), float startSize = 0.125f, float endSize = 0.125f) {
  421.         LineRenderer lr = MakeArcArrow(ref lineObj, angle, pointCount, arrowHeadSize, normal, firstPoint, center, color, startSize, endSize);
  422.         ReverseLineInternal(ref lr);
  423.         Vector3[] p = new Vector3[lr.positionCount];
  424.         lr.GetPositions(p);
  425.         lr = MakeArrow(ref lineObj, p, p.Length, arrowHeadSize, color, endSize, startSize, lr.widthCurve.keys);
  426.         ReverseLineInternal(ref lr);
  427.         return lr;
  428.     }
  429.  
  430.     public static void DrawQuaternion(ref GameObject axisObj, ref GameObject angleObj, Quaternion quaternion,
  431.         Vector3 position=default(Vector3), Vector3 startPoint=default(Vector3), Quaternion orientation=default(Quaternion),
  432.         float arrowHeadSize = 2, Color color=default(Color), int arcPoints = 24, float lineSize = 0.125f) {
  433.         if (orientation == default(Quaternion)) { orientation = Quaternion.identity; }
  434.         if (startPoint == default(Vector3)) { startPoint = Vector3.forward; }
  435.         float angle;
  436.         Vector3 axis;
  437.         quaternion.ToAngleAxis (out angle, out axis);
  438.         Vector3 axisRotated = orientation * axis;
  439.         Lines.MakeArrow (ref axisObj, position - axisRotated/2, position + axisRotated/2, arrowHeadSize, color, lineSize, lineSize);
  440.         Lines.MakeArcArrow (ref angleObj, angle, arcPoints, arrowHeadSize, axisRotated, startPoint, position, color, lineSize, lineSize);
  441.     }
  442. }
RAW Paste Data
Top