public static void DrawOtherPoints(BezierCurve curve, BezierPoint caller) { foreach(BezierPoint p in curve.GetAnchorPoints()) { if(p != caller) DrawPointSceneGUI(p); } }
void OnEnable(){ point = (BezierPoint)target; handleTypeProp = serializedObject.FindProperty("handleStyle"); handle1Prop = serializedObject.FindProperty("_handle1"); handle2Prop = serializedObject.FindProperty("_handle2"); }
public BezierSpline CreateSpline() { IList<IControlPoint> points = GetChildList<IControlPoint>(Schema.bezierType.pointChild); BezierSpline spline = new BezierSpline(); spline.IsClosed = GetAttribute<bool>(Schema.bezierType.isClosedAttribute); BezierPoint bpt = new BezierPoint(); foreach (var cpt in points) { bpt.Position = cpt.Translation; spline.Add(bpt); } return spline; }
public static void DrawCurveMirrored(Transform localTransform, BezierPoint p1, BezierPoint p2, float resolution, Axis axis) { DrawCurveMirrored(localTransform, p1, p2, GetNumPoints(p1, p2, resolution), axis); }
public bool RemovePoint(BezierPoint point) { _dirty = _points.Remove(point); return(_dirty); }
/// <summary> /// - Approximates the length /// </summary> /// <returns> /// - The approximate length /// </returns> /// <param name='p1'> /// - The bezier point at the start of the curve /// </param> /// <param name='p2'> /// - The bezier point at the end of the curve /// </param> /// <param name='resolution'> /// - The number of points along the curve used to create measurable segments /// </param> public static float ApproximateLength(BezierPoint p1, BezierPoint p2, int resolution = 10) { float _res = resolution; float total = 0; Vector3 lastPosition = p1.position; Vector3 currentPosition; for(int i = 0; i < resolution + 1; i++) { currentPosition = GetPoint(p1, p2, i / _res); total += (currentPosition - lastPosition).magnitude; lastPosition = currentPosition; } return total; }
private static void HandleConnected(BezierPoint p){ Handles.color = Color.cyan; Vector3 newGlobal1 = Handles.FreeMoveHandle(p.globalHandle1, p.transform.rotation, HandleUtility.GetHandleSize(p.globalHandle1)*0.15f, Vector3.zero, Handles.SphereCap); if(newGlobal1 != p.globalHandle1){ Undo.RecordObject(p, "Move Handle"); p.globalHandle1 = newGlobal1; p.globalHandle2 = -(newGlobal1 - p.position) + p.position; } Vector3 newGlobal2 = Handles.FreeMoveHandle(p.globalHandle2, p.transform.rotation, HandleUtility.GetHandleSize(p.globalHandle2)*0.15f, Vector3.zero, Handles.SphereCap); if(newGlobal2 != p.globalHandle2){ Undo.RecordObject(p, "Move Handle"); p.globalHandle1 = -(newGlobal2 - p.position) + p.position; p.globalHandle2 = newGlobal2; } }
/// <summary> /// - Removes the given point from the curve ("points" array) /// </summary> /// <param name='point'> /// - The point to remove /// </param> public void RemovePoint(BezierPoint point) { List<BezierPoint> tempArray = new List<BezierPoint>(points); tempArray.Remove(point); points = tempArray.ToArray(); dirty = false; }
/// <summary> /// - Draws the curve in the Editor /// </summary> /// <param name='p1'> /// - The bezier point at the beginning of the curve /// </param> /// <param name='p2'> /// - The bezier point at the end of the curve /// </param> /// <param name='resolution'> /// - The number of segments along the curve to draw /// </param> public static void DrawCurve(BezierPoint p1, BezierPoint p2, int resolution) { int limit = resolution+1; float _res = resolution; Vector3 lastPoint = p1.position; Vector3 currentPoint = Vector3.zero; for(int i = 1; i < limit; i++){ currentPoint = GetPoint(p1, p2, i/_res); Gizmos.DrawLine(lastPoint, currentPoint); lastPoint = currentPoint; } }
public HitTestResult(Link link, BezierPoint controlHandle) { Link = link; ControlHandle = controlHandle; }
// Helper method for finding a pair of points and a corresponding local 't' for given global 't' TBetweenPointsData GetTBetweenPoints(float t) { if (t <= 0) { return(new TBetweenPointsData { p1 = points[0], p2 = points[1], t = 0 }); } else if (t >= 1) { if (close) { return(new TBetweenPointsData { p1 = points[points.Length - 1], p2 = points[0], t = 1 }); } else { return(new TBetweenPointsData { p1 = points[points.Length - 2], p2 = points[points.Length - 1], t = 1 }); } } else { float totalPercent = 0; float curvePercent = 0; BezierPoint p1 = null; BezierPoint p2 = null; int approxResolution = 10; int safetyCounter = 0; int maxIters = 10; while (p1 == null && p2 == null) { totalPercent = 0; int end = close ? points.Length : points.Length - 1; for (int i = 0; i < end; i++) { var pa = points[i]; var pb = points[(i + 1) % points.Length]; curvePercent = ApproximateLength(pa, pb, approxResolution) / length; if ((totalPercent + curvePercent > t) || Mathf.Abs(t - (totalPercent + curvePercent)) < 5e-6) { p1 = pa; p2 = pb; break; } else { totalPercent += curvePercent; } } approxResolution += 10; if (++safetyCounter >= maxIters) { Debug.LogError("BezierCurve couldn't find a point", this); return(default(TBetweenPointsData)); } } if (p1 == null) { Debug.LogError("p1 is null"); } if (p2 == null) { Debug.LogError("p2 is null"); } var ret = new TBetweenPointsData(); ret.p1 = p1; ret.p2 = p2; ret.t = (t - totalPercent) / curvePercent; return(ret); } }
/// <summary> /// Returns the number of points required to interpolate the given bezier points to a given resolution. /// </summary> public static int GetNumPoints(BezierPoint p1, BezierPoint p2, float resolution) { return(GetNumPoints(p1.position, p1.globalHandle2, p2.position, p2.globalHandle1, resolution)); }
public override void OnMouseUp(ExMouseEventArgs e) { base.OnMouseUp(e); PressMouseButton = MouseButtons.None; //MouseDownObject = HitTestResult.Empty; if (NewLineFrom != null) { EndNewLineTest(e); e.Suppress = true; } else if (e.Button == MouseButtons.Left && PressedObject.Link != null && Helper.TestModifierKeys(Keys.Shift)) { if (!string.IsNullOrEmpty(PressedObject.Link.Hyperlink)) { Helper.OpenUrl(PressedObject.Link.Hyperlink); } } else { if (DragingControlHandle != BezierPoint.None && TempLayout != null && SelectedObject.Link != null) { Link line = SelectedObject.Link; var oldPoints = line.GetBezierPoints(); //Rectangle rect = line.Bounds; Point pt = View.PointToLogic(new Point(e.X, e.Y)); Point pts; Topic topic; switch (DragingControlHandle) { case BezierPoint.StartPoint: topic = View.GetTopicAt(e.X, e.Y); if (line.CanStartFrom(topic)) { line.From = topic; } break; case BezierPoint.EndPoint: topic = View.GetTopicAt(e.X, e.Y); if (line.CanEndTo(topic)) { line.Target = topic; } break; case BezierPoint.ControlPoint1: pts = PaintHelper.CenterPoint(line.LayoutData.StartBounds); //line.LayoutData.CPLength1 = PaintHelper.GetDistance(pts, pt); //line.LayoutData.CPAngle1 = PaintHelper.GetAngle(pts, pt); line.LayoutData.CP1 = new BezierControlPoint(PaintHelper.GetAngle(pts, pt), PaintHelper.GetDistance(pts, pt)); break; case BezierPoint.ControlPoint2: pts = PaintHelper.CenterPoint(line.LayoutData.EndBounds); //line.LayoutData.CPLength2 = PaintHelper.GetDistance(pts, pt); //line.LayoutData.CPAngle2 = PaintHelper.GetAngle(pts, pt); line.LayoutData.CP2 = new BezierControlPoint(PaintHelper.GetAngle(pts, pt), PaintHelper.GetDistance(pts, pt)); break; } line.RefreshLayout(); line.SetChanged(); TempLayout = line.LayoutData.Clone(); InvalidateLink(oldPoints, line.Width, true); InvalidateLink(line, false); //InvalidateLinkRegion(oldPoints, line.GetBezierPoints(), line.LineWidth); /*if (rect.IsEmpty) * rect = line.Bounds; * else * rect = Rectangle.Union(rect, line.Bounds); * rect.Location = View.PointToReal(rect.Location); * InvalidateChart(rect, true);*/ } DragingControlHandle = BezierPoint.None; } }
public static float ApproximateLength(BezierPoint p1, BezierPoint p2, float resolution = 0.5f) { int numPoints = GetNumPoints(p1, p2, resolution); return(ApproximateLength(p1, p2, numPoints)); }
/// <summary> /// - Approximates the length /// </summary> /// <returns> /// - The approximate length /// </returns> /// <param name='p1'> /// - The bezier point at the start of the curve /// </param> /// <param name='p2'> /// - The bezier point at the end of the curve /// </param> /// <param name='numPoints'> /// - The number of points along the curve used to create measurable segments /// </param> public static float ApproximateLength(BezierPoint p1, BezierPoint p2, int numPoints = 10) { return(ApproximateLength(p1.position, p1.globalHandle2, p2.position, p2.globalHandle1, numPoints)); }
public static Vector3 GetPoint(BezierPoint p1, BezierPoint p2, float t) { return(GetPoint(p1.position, p1.globalHandle2, p2.position, p2.globalHandle1, t)); }
static void DrawPointSceneGUI(BezierPoint point) { Handles.Label(point.position + new Vector3(0, HandleUtility.GetHandleSize(point.position) * 0.4f, 0), point.gameObject.name); Handles.color = Color.green; Vector3 newPosition = Handles.FreeMoveHandle(point.position, point.transform.rotation, HandleUtility.GetHandleSize(point.position)*0.1f, Vector3.zero, Handles.RectangleCap); if(newPosition != point.position) { Undo.RegisterUndo(point.transform, "Move Point"); point.transform.position = newPosition; } if(point.handleStyle != BezierPoint.HandleStyle.None) { Handles.color = Color.cyan; Vector3 newGlobal1 = Handles.FreeMoveHandle(point.globalHandle1, point.transform.rotation, HandleUtility.GetHandleSize(point.globalHandle1)*0.075f, Vector3.zero, Handles.CircleCap); if(point.globalHandle1 != newGlobal1) { Undo.RegisterUndo(point, "Move Handle"); point.globalHandle1 = newGlobal1; if(point.handleStyle == BezierPoint.HandleStyle.Connected) point.globalHandle2 = -(newGlobal1 - point.position) + point.position; } Vector3 newGlobal2 = Handles.FreeMoveHandle(point.globalHandle2, point.transform.rotation, HandleUtility.GetHandleSize(point.globalHandle2)*0.075f, Vector3.zero, Handles.CircleCap); if(point.globalHandle2 != newGlobal2) { Undo.RegisterUndo(point, "Move Handle"); point.globalHandle2 = newGlobal2; if(point.handleStyle == BezierPoint.HandleStyle.Connected) point.globalHandle1 = -(newGlobal2 - point.position) + point.position; } Handles.color = Color.yellow; Handles.DrawLine(point.position, point.globalHandle1); Handles.DrawLine(point.position, point.globalHandle2); } }
void DrawPointInspector(BezierPoint point, int index) { SerializedObject serObj = new SerializedObject(point); SerializedProperty handleStyleProp = serObj.FindProperty("handleStyle"); SerializedProperty handle1Prop = serObj.FindProperty("_handle1"); SerializedProperty handle2Prop = serObj.FindProperty("_handle2"); EditorGUILayout.BeginHorizontal(); if (GUILayout.Button("X", GUILayout.Width(20))) { //Undo.RegisterUndo("Remove Point"); pointsProp.MoveArrayElement(curve.GetPointIndex(point), curve.pointCount - 1); pointsProp.arraySize--; DestroyImmediate(point.gameObject); return; } EditorGUILayout.ObjectField(point.gameObject, typeof(GameObject), true); if (index != 0 && GUILayout.Button(@"/\", GUILayout.Width(25))) { UnityEngine.Object other = pointsProp.GetArrayElementAtIndex(index - 1).objectReferenceValue; pointsProp.GetArrayElementAtIndex(index - 1).objectReferenceValue = point; pointsProp.GetArrayElementAtIndex(index).objectReferenceValue = other; } if (index != pointsProp.arraySize - 1 && GUILayout.Button(@"\/", GUILayout.Width(25))) { UnityEngine.Object other = pointsProp.GetArrayElementAtIndex(index + 1).objectReferenceValue; pointsProp.GetArrayElementAtIndex(index + 1).objectReferenceValue = point; pointsProp.GetArrayElementAtIndex(index).objectReferenceValue = other; } EditorGUILayout.EndHorizontal(); EditorGUI.indentLevel++; EditorGUI.indentLevel++; int newType = (int)((object)EditorGUILayout.EnumPopup("Handle Type", (BezierPoint.HandleStyle)handleStyleProp.enumValueIndex)); if (newType != handleStyleProp.enumValueIndex) { handleStyleProp.enumValueIndex = newType; if (newType == 0) { if (handle1Prop.vector3Value != Vector3.zero) { handle2Prop.vector3Value = -handle1Prop.vector3Value; } else if (handle2Prop.vector3Value != Vector3.zero) { handle1Prop.vector3Value = -handle2Prop.vector3Value; } else { handle1Prop.vector3Value = new Vector3(0.1f, 0, 0); handle2Prop.vector3Value = new Vector3(-0.1f, 0, 0); } } else if (newType == 1) { if (handle1Prop.vector3Value == Vector3.zero && handle2Prop.vector3Value == Vector3.zero) { handle1Prop.vector3Value = new Vector3(0.1f, 0, 0); handle2Prop.vector3Value = new Vector3(-0.1f, 0, 0); } } else if (newType == 2) { handle1Prop.vector3Value = Vector3.zero; handle2Prop.vector3Value = Vector3.zero; } } Vector3 newPointPos = EditorGUILayout.Vector3Field("Position : ", point.transform.localPosition); if (newPointPos != point.transform.localPosition) { Undo.RecordObject(point.transform, "Move Bezier Point"); point.transform.localPosition = newPointPos; } if (handleStyleProp.enumValueIndex == 0) { Vector3 newPosition; newPosition = EditorGUILayout.Vector3Field("Handle 1", handle1Prop.vector3Value); if (newPosition != handle1Prop.vector3Value) { handle1Prop.vector3Value = newPosition; handle2Prop.vector3Value = -newPosition; } newPosition = EditorGUILayout.Vector3Field("Handle 2", handle2Prop.vector3Value); if (newPosition != handle2Prop.vector3Value) { handle1Prop.vector3Value = -newPosition; handle2Prop.vector3Value = newPosition; } } else if (handleStyleProp.enumValueIndex == 1) { EditorGUILayout.PropertyField(handle1Prop); EditorGUILayout.PropertyField(handle2Prop); } EditorGUI.indentLevel--; EditorGUI.indentLevel--; if (GUI.changed) { serObj.ApplyModifiedProperties(); EditorUtility.SetDirty(serObj.targetObject); } }
void DrawPointInspector(BezierPoint point, int index) { SerializedObject serObj = new SerializedObject(point); SerializedProperty handleStyleProp = serObj.FindProperty("handleStyle"); SerializedProperty handle1Prop = serObj.FindProperty("_handle1"); SerializedProperty handle2Prop = serObj.FindProperty("_handle2"); EditorGUILayout.BeginHorizontal(); if(GUILayout.Button("X", GUILayout.Width(20))) { Undo.RegisterSceneUndo("Remove Point"); pointsProp.MoveArrayElement(curve.GetPointIndex(point), curve.pointCount - 1); pointsProp.arraySize--; DestroyImmediate(point.gameObject); return; } EditorGUILayout.ObjectField(point.gameObject, typeof(GameObject), true); if(index != 0 && GUILayout.Button(@"/\", GUILayout.Width(25))) { UnityEngine.Object other = pointsProp.GetArrayElementAtIndex(index - 1).objectReferenceValue; pointsProp.GetArrayElementAtIndex(index - 1).objectReferenceValue = point; pointsProp.GetArrayElementAtIndex(index).objectReferenceValue = other; } if(index != pointsProp.arraySize - 1 && GUILayout.Button(@"\/", GUILayout.Width(25))) { UnityEngine.Object other = pointsProp.GetArrayElementAtIndex(index + 1).objectReferenceValue; pointsProp.GetArrayElementAtIndex(index + 1).objectReferenceValue = point; pointsProp.GetArrayElementAtIndex(index).objectReferenceValue = other; } EditorGUILayout.EndHorizontal(); EditorGUI.indentLevel++; EditorGUI.indentLevel++; int newType = (int)((object)EditorGUILayout.EnumPopup("Handle Type", (BezierPoint.HandleStyle)handleStyleProp.enumValueIndex)); if(newType != handleStyleProp.enumValueIndex) { handleStyleProp.enumValueIndex = newType; if(newType == 0) { if(handle1Prop.vector3Value != Vector3.zero) handle2Prop.vector3Value = -handle1Prop.vector3Value; else if(handle2Prop.vector3Value != Vector3.zero) handle1Prop.vector3Value = -handle2Prop.vector3Value; else { handle1Prop.vector3Value = new Vector3(0.1f, 0, 0); handle2Prop.vector3Value = new Vector3(-0.1f, 0, 0); } } else if(newType == 1) { if(handle1Prop.vector3Value == Vector3.zero && handle2Prop.vector3Value == Vector3.zero) { handle1Prop.vector3Value = new Vector3(0.1f, 0, 0); handle2Prop.vector3Value = new Vector3(-0.1f, 0, 0); } } else if(newType == 2) { handle1Prop.vector3Value = Vector3.zero; handle2Prop.vector3Value = Vector3.zero; } } Vector3 newPointPos = EditorGUILayout.Vector3Field("Position : ", point.transform.localPosition); if(newPointPos != point.transform.localPosition) { Undo.RegisterUndo(point.transform, "Move Bezier Point"); point.transform.localPosition = newPointPos; } if(handleStyleProp.enumValueIndex == 0) { Vector3 newPosition; newPosition = EditorGUILayout.Vector3Field("Handle 1", handle1Prop.vector3Value); if(newPosition != handle1Prop.vector3Value) { handle1Prop.vector3Value = newPosition; handle2Prop.vector3Value = -newPosition; } newPosition = EditorGUILayout.Vector3Field("Handle 2", handle2Prop.vector3Value); if(newPosition != handle2Prop.vector3Value) { handle1Prop.vector3Value = -newPosition; handle2Prop.vector3Value = newPosition; } } else if(handleStyleProp.enumValueIndex == 1) { EditorGUILayout.PropertyField(handle1Prop); EditorGUILayout.PropertyField(handle2Prop); } EditorGUI.indentLevel--; EditorGUI.indentLevel--; if(GUI.changed) { serObj.ApplyModifiedProperties(); EditorUtility.SetDirty(serObj.targetObject); } }
/// <summary> /// 读取XML中的贝塞尔曲线内容 /// </summary> /// <param name="beziernode"></param> /// <param name="pic"></param> public static void ReadBezierLine(XmlNode beziernode, PicTabPage pic) { XmlElement bezierElement = (XmlElement)beziernode; int ID = int.Parse(bezierElement.GetAttribute("ID")); double StrokeThickness = double.Parse(bezierElement.GetAttribute("StrokeThickness")); ///读取起始点 XmlElement startPoint = (XmlElement)beziernode.SelectSingleNode("StartPoint"); BezierPoint readStartBezierPoint = new BezierPoint(); int startID = -1; int startfatherID = -1; foreach (XmlNode node in startPoint.ChildNodes) { XmlElement nodeElenemt = (XmlElement)node; switch (nodeElenemt.Name) { case "PositionType": readStartBezierPoint.positionType = XAribute.XPositonStyleMapping(nodeElenemt.InnerText); break; case "LinkAributeID": startID = int.Parse(nodeElenemt.InnerText); break; case "LinkAributeFatherID": startfatherID = int.Parse(nodeElenemt.InnerText); break; default: break; } } ///读取结束点 XmlElement endPoint = (XmlElement)beziernode.SelectSingleNode("EndPoint"); BezierPoint readEndBezierPoint = new BezierPoint(); int endID = -1; int endfatherID = -1; foreach (XmlNode node in endPoint.ChildNodes) { XmlElement nodeElenemt = (XmlElement)node; switch (nodeElenemt.Name) { case "PositionType": readEndBezierPoint.positionType = XAribute.XPositonStyleMapping(nodeElenemt.InnerText); break; case "LinkAributeID": endID = int.Parse(nodeElenemt.InnerText); break; case "LinkAributeFatherID": endfatherID = int.Parse(nodeElenemt.InnerText); break; default: break; } } BezierLine readBezierLine = new BezierLine(ID); readBezierLine.StartPoint = readStartBezierPoint; readBezierLine.EndPoint = readEndBezierPoint; pic.ReadCreateBezierLine(readBezierLine, startID, endID, startfatherID, endfatherID); }
/// <summary> /// - Adds the given point to the end of the curve ("points" array) /// </summary> /// <param name='point'> /// - The point to add. /// </param> public void AddPoint(BezierPoint point) { List<BezierPoint> tempArray = new List<BezierPoint>(points); tempArray.Add(point); points = tempArray.ToArray(); dirty = true; }
public static bool IsNearBezier(Vector2 p, BezierPoint point1, BezierPoint point2, float rad) { if (point1.curve2 != point2.curve1) { Debug.LogError ("Curves Not The Same"); return false; } BezierCurve curve = point1.curve2; var r = curve.rect; r.x-=rad; r.y-=rad; r.width+=rad*2; r.height+=rad*2; if (!r.Contains (p)) { return false; } var nearest = NearestPointOnBezier (p,curve,0.1f,false); var sec = point1.curve2.aproxLength/10; if ((nearest-p).sqrMagnitude>=(sec*3)*(sec*3)) { return false; } nearest = NearestPointOnBezier (p,curve,0.01f,true); if ((nearest-p).sqrMagnitude<=rad*rad) { return true; } return false; }
/// <summary> /// - Get the index of the given point in this curve /// </summary> /// <returns> /// - The index, or -1 if the point is not found /// </returns> /// <param name='point'> /// - Point to search for /// </param> public int GetPointIndex(BezierPoint point) { int result = -1; for(int i = 0; i < points.Length; i++) { if(points[i] == point) { result = i; break; } } return result; }
public static bool IsNearBeziers(Vector2 p, BezierPoint[] points, float rad) { for (var i=0;i<points.Length-1;i++) { if (IsNearBezier (p,points[i],points[i+1],rad)) { return true; } } return false; }
/// <summary> /// - Gets the point 't' percent along a curve /// - Automatically calculates for the number of relevant points /// </summary> /// <returns> /// - The point 't' percent along the curve /// </returns> /// <param name='p1'> /// - The bezier point at the beginning of the curve /// </param> /// <param name='p2'> /// - The bezier point at the end of the curve /// </param> /// <param name='t'> /// - Value between 0 and 1 representing the percent along the curve (0 = 0%, 1 = 100%) /// </param> public static Vector3 GetPoint(BezierPoint p1, BezierPoint p2, float t) { if(p1.handle2 != Vector3.zero) { if(p2.handle1 != Vector3.zero) return GetCubicCurvePoint(p1.position, p1.globalHandle2, p2.globalHandle1, p2.position, t); else return GetQuadraticCurvePoint(p1.position, p1.globalHandle2, p2.position, t); } else { if(p2.handle1 != Vector3.zero) return GetQuadraticCurvePoint(p1.position, p2.globalHandle1, p2.position, t); else return GetLinearPoint(p1.position, p2.position, t); } }
private static void HandleAbsent(BezierPoint p) { p.handle1 = Vector3.zero; p.handle2 = Vector3.zero; }
public static void DrawBezier(BezierPoint[] points, float rad, Color col, Texture2D tex) { rad = Mathf.Round(rad);//It is important to round the numbers otherwise it will mess up with the texture width if (points.Length <= 1) { return; } Vector2 topleft = new Vector2(Mathf.Infinity, Mathf.Infinity); Vector2 bottomright = new Vector2(0, 0); for (var i = 0; i < points.Length - 1; i++) { BezierCurve curve = new BezierCurve(points[i].main, points[i].control2, points[i + 1].control1, points[i + 1].main ); points[i].curve2 = curve; points[i + 1].curve1 = curve; topleft.x = Mathf.Min(topleft.x, curve.rect.x); topleft.y = Mathf.Min(topleft.y, curve.rect.y); bottomright.x = Mathf.Max(bottomright.x, curve.rect.x + curve.rect.width); bottomright.y = Mathf.Max(bottomright.y, curve.rect.y + curve.rect.height); } topleft -= new Vector2(rad, rad); bottomright += new Vector2(rad, rad); var start = new Vector2(Mathf.Clamp(topleft.x, 0, tex.width), Mathf.Clamp(topleft.y, 0, tex.height)); var width = new Vector2(Mathf.Clamp(bottomright.x - topleft.x, 0, tex.width - start.x), Mathf.Clamp(bottomright.y - topleft.y, 0, tex.height - start.y)); Color[] pixels = tex.GetPixels((int)start.x, (int)start.y, (int)width.x, (int)width.y, 0); for (var y = 0; y < width.y; y++) { for (var x = 0; x < width.x; x++) { var p = new Vector2(x + start.x, y + start.y); if (!Mathfx.IsNearBeziers(p, points, rad + 2)) { continue; } var samples = Sample(p); var c = Color.black; var pc = pixels[(int)(y * width.x + x)];//Previous pixel color for (var i = 0; i < samples.Length; i++) { if (Mathfx.IsNearBeziers(samples[i], points, rad)) { c += col; } else { c += pc; } } c /= samples.Length; pixels[(int)(y * width.x + x)] = c; } } tex.SetPixels((int)start.x, (int)start.y, (int)width.x, (int)width.y, pixels, 0); tex.Apply(); }
//create bezier waypoint void PlaceBezierPoint(Vector3 placePos) { //create new bezier point property class BezierPoint newPoint = new BezierPoint(); //instantiate waypoint gameobject GameObject wayp = new GameObject("Waypoint"); //assign waypoint to the class newPoint.wp = wayp.transform; //same as in PlaceWaypoint(), //but we have to restrict x, z values due to minor issues with bezier points if (bwpList.Count == 0) bezierPathMan.transform.position = new Vector3(0, placePos.y, 0); //overwrite bezier points for the first point, //because some weird stuff is going on when repositioning the path //once finished, the exact bezier positions will get recalculated anyways if (bwpList.Count == 1) { bwpList[0].bp = new[] { bwpList[0].wp.transform.position - new Vector3(2, 0, 0), bwpList[0].wp.transform.position + new Vector3(0, 0, 2) }; } //position current waypoint at clicked position in scene view wayp.transform.position = placePos; //look up and parent it to the defined path wayp.transform.parent = bezierPathMan.transform; //zero out its y-value to correctly work in 2D space Vector3 localPos = wayp.transform.localPosition; localPos.y = 0f; wayp.transform.localPosition = localPos; //create new array with bezier point handle positions for this waypoint newPoint.bp = new[] { placePos - new Vector3(2, 0, 0), placePos + new Vector3(0, 0, 2) }; //add waypoint to the list of waypoints bezierPathMan.points.Add(newPoint); //add waypoint to temporary list bwpList.Add(newPoint); //rename waypoint to match the list count wayp.name = "Waypoint" + (bwpList.Count - 1); }
private static void HandleBroken(BezierPoint p){ Handles.color = Color.cyan; Vector3 newGlobal1 = Handles.FreeMoveHandle(p.globalHandle1, Quaternion.identity, HandleUtility.GetHandleSize(p.globalHandle1)*0.15f, Vector3.zero, Handles.SphereCap); Vector3 newGlobal2 = Handles.FreeMoveHandle(p.globalHandle2, Quaternion.identity, HandleUtility.GetHandleSize(p.globalHandle2)*0.15f, Vector3.zero, Handles.SphereCap); if(newGlobal1 != p.globalHandle1) { Undo.RecordObject(p, "Move Handle"); p.globalHandle1 = newGlobal1; } if(newGlobal2 != p.globalHandle2) { Undo.RecordObject(p, "Move Handle"); p.globalHandle2 = newGlobal2; } }
public static void DrawCurve(BezierPoint p1, BezierPoint p2, float resolution) { DrawCurve(p1, p2, GetNumPoints(p1, p2, resolution)); }
//adds a waypoint when clicking on the "+" button in the inspector private void AddWaypointAtIndex(int index) { //register all scene objects so we can undo to this current state //before adding this waypoint easily Undo.RegisterSceneUndo("WPAdd"); //create a new waypoint property class BezierPoint point = new BezierPoint(); //create new waypoint gameobject GameObject wp = new GameObject("Waypoint"); //set its position to the last one wp.transform.position = script.points[index].wp.position; //assign it to the class point.wp = wp.transform; //assign new bezier point positions point.bp = new[] { wp.transform.position - new Vector3(2f, 0f, 0f), wp.transform.position + new Vector3(0, 0, 2f) }; //parent it to the path gameobject wp.transform.parent = script.transform; //zero out its y-value to correctly work in 2D space Vector3 localPos = wp.transform.localPosition; localPos.y = 0f; wp.transform.localPosition = localPos; //finally, insert this new waypoint after the one clicked in the list script.points.Insert(index + 1, point); }
public override void OnInspectorGUI() { //don't draw inspector fields if the path contains less than 2 points //(a path with less than 2 points really isn't a path) if (script.points.Count < 2) return; //create new color fields for editing waypoint gizmo colors script.color1 = EditorGUILayout.ColorField("Color1", script.color1); script.color2 = EditorGUILayout.ColorField("Color2", script.color2); script.color3 = EditorGUILayout.ColorField("Color3", script.color3); //let iTween calculate path length of all waypoints float pathLength = iTween.PathLength(script.waypoints); //path length label, show calculated path length GUILayout.Label("Straight Path Length: " + pathLength); //checkbox Field to enable editable path properties EditorGUILayout.BeginHorizontal(); script.showGizmos = EditorGUILayout.Toggle("Show Gizmos", script.showGizmos); EditorGUILayout.EndHorizontal(); //check if the path gameobject position has changed since the last call if (!script.showGizmos && script.transform.position != oldGizmoPos) { //if not in edit mode, ignore user input script.transform.position = oldGizmoPos; } else { //calculate the difference between the two positions Vector3 difPos = script.transform.position - oldGizmoPos; oldGizmoPos = script.transform.position; if (difPos != Vector3.zero) { //enable edit mode when moving the path object script.showGizmos = true; //add the difference to the bezier points per waypoint, //so they are moving with the path for (int i = 0; i < script.points.Count; i++) { script.points[i].bp[0] += difPos; script.points[i].bp[1] += difPos; } } } //hide following settings if (!script.showGizmos) return; //Float Field to modify the distance between generated path points EditorGUILayout.BeginHorizontal(); script.spacing = EditorGUILayout.FloatField("Spacing", script.spacing); EditorGUILayout.EndHorizontal(); //Int Slider to modify the smoothing factor of the final path EditorGUILayout.BeginHorizontal(); script.interpolations = EditorGUILayout.IntSlider("Interpolations", script.interpolations, 0, 4); EditorGUILayout.EndHorizontal(); //waypoint index header GUILayout.Label("Waypoints: ", EditorStyles.boldLabel); //loop through the waypoint array for (int i = 0; i < script.points.Count; i++) { GUILayout.BeginHorizontal(); //indicate each array slot with index number in front of it GUILayout.Label((i + 1) + ".", GUILayout.Width(20)); //create an object field for every waypoint var result = EditorGUILayout.ObjectField(script.points[i].wp, typeof(Transform), true) as Transform; //if the object field has changed, set waypoint to new input if (GUI.changed) script.points[i].wp = result; //display an "Add Waypoint" button for every array row except the last one //on click we call AddWaypointAtIndex() to insert a new waypoint slot AFTER the selected slot if (i < script.points.Count - 1 && GUILayout.Button("+", GUILayout.Width(30f))) { AddWaypointAtIndex(i); break; } //display an "Remove Waypoint" button for every array row except the first and last one //on click we call RemoveWaypointAtIndex() to delete the selected waypoint slot if (i > 0 && i < script.points.Count - 1 && GUILayout.Button("-", GUILayout.Width(30f))) { RemoveWaypointAtIndex(i); break; } GUILayout.EndHorizontal(); } EditorGUILayout.Space(); //invert direction of whole path if (GUILayout.Button("Invert Direction")) { //register all scene objects so we can undo to this current state //before inverting all waypoints easily Undo.RegisterSceneUndo("WPInvert"); //Array.Copy() just gives us references and would change both arrays, //so we classically create a new array with length of the current one, //loop through them and copy all position data to the newly created array BezierPoint[] waypointCache = new BezierPoint[script.points.Count]; //cache "old value" for (int i = 0; i < waypointCache.Length; i++) { waypointCache[i] = script.points[i]; } //reverse order based on the old list for (int i = 0; i < waypointCache.Length; i++) { script.points[waypointCache.Length - 1 - i] = waypointCache[i]; } //rename the first and last waypoint to match the new order script.points[0].wp.name = "WaypointStart"; script.points[script.points.Count - 1].wp.name = "WaypointEnd"; } EditorGUILayout.Space(); //draw object field for waypoint prefab script.waypointPrefab = (GameObject)EditorGUILayout.ObjectField("Waypoint Prefab", script.waypointPrefab, typeof(GameObject), true); //replace all waypoints with the prefab if (GUILayout.Button("Replace Waypoints")) { //abort if no waypoint is set if (script.waypointPrefab == null) { Debug.LogWarning("No Waypoint Prefab set. Aborting."); return; } ReplaceWaypoints(); } if (GUI.changed) SceneView.RepaintAll(); }
void test() { float startTime = Time.realtimeSinceStartup; var w = 100; var h = 100; var p1 = new BezierPoint(new Vector2(10, 0), new Vector2(5, 20), new Vector2(20, 0)); var p2 = new BezierPoint(new Vector2(50, 10), new Vector2(40, 20), new Vector2(60, -10)); var c = new BezierCurve(p1.main, p1.control2, p2.control1, p2.main); p1.curve2 = c; p2.curve1 = c; Vector2 elapsedTime = new Vector2((Time.realtimeSinceStartup - startTime) * 10, 0); float startTime2 = Time.realtimeSinceStartup; for (var i = 0; i < w * h; i++) { Mathfx.IsNearBezier(new Vector2(Random.value * 80, Random.value * 30), p1, p2, 10); } Vector2 elapsedTime2 = new Vector2((Time.realtimeSinceStartup - startTime2) * 10, 0); Debug.Log("Drawing took " + elapsedTime.ToString() + " " + elapsedTime2.ToString()); }
public void AddPoint(BezierPoint point) { _points.Add(point); _dirty = true; }