private void DrawClosestPointOnLine() { Event currentEvent = Event.current; if (currentEvent.modifiers == EventModifiers.Control) { Vector3 pointPos = HandleUtility.ClosestPointToPolyLine(lines); Color prevColor = Handles.color; Handles.color = sphereColor; Handles.DrawSolidDisc(pointPos, Camera.current.transform.forward, HandleUtility.GetHandleSize(pointPos) * 0.1f); Handles.color = prevColor; HandleUtility.Repaint(); if (currentEvent.type == EventType.MouseDown && currentEvent.button == 0) { GUIUtility.hotControl = 0; int index = GetIndextOfClosestLine(pointPos); pointsProperty.InsertArrayElementAtIndex(index); serializedObject.ApplyModifiedProperties(); waypoints[index] = pointPos; CreateSegments(); CreateLines(); currentEvent.Use(); } } }
protected Vector3 ClosestPoint(Transform t, Vector2[] verts) { // Duplicate the verts list and make it into a loop. var loop = new List <Vector2>(verts); loop.Add(verts[0]); Vector3[] arr = loop.Select <Vector2, Vector3>((arg) => (Vector3)t.TransformPoint(arg)).ToArray(); return(HandleUtility.ClosestPointToPolyLine(arr)); }
void OnSceneGUI() { Rope rope = (target as Rope); Vector3[] localPoints = rope.nodes.ToArray(); Vector3[] worldPoints = new Vector3[rope.nodes.Count]; for (int i = 0; i < worldPoints.Length; i++) { worldPoints[i] = rope.transform.TransformPoint(localPoints[i]); } DrawPolyLine(worldPoints); DrawNodes(rope, worldPoints); DrawHinges(rope); if (Event.current.shift) { //Adding Points Vector3 mousePos = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition).origin; Vector3 polyLocalMousePos = rope.transform.InverseTransformPoint(mousePos); Vector3 nodeOnPoly = HandleUtility.ClosestPointToPolyLine(worldPoints); float handleSize = HandleUtility.GetHandleSize(nodeOnPoly); int nodeIndex = FindNodeIndex(worldPoints, nodeOnPoly); Handles.DrawLine(worldPoints[nodeIndex - 1], mousePos); Handles.DrawLine(worldPoints[nodeIndex], mousePos); if (Handles.Button(mousePos, Quaternion.identity, handleSize * 0.1f, handleSize, HandleFunc)) { polyLocalMousePos.z = 0; Undo.RecordObject(rope, "Insert Node"); rope.nodes.Insert(nodeIndex, polyLocalMousePos); UpdateRope(rope); Event.current.Use(); } } if (Event.current.control && rope.nodes.Count > 2) { //Deleting Points int indexToDelete = FindNearestNodeToMouse(worldPoints); Handles.color = Color.red; float handleSize = HandleUtility.GetHandleSize(worldPoints[0]); if (Handles.Button(worldPoints[indexToDelete], Quaternion.identity, handleSize * 0.09f, handleSize, DeleteHandleFunc)) { Undo.RecordObject(rope, "Remove Node"); rope.nodes.RemoveAt(indexToDelete); indexToDelete = -1; UpdateRope(rope); Event.current.Use(); } Handles.color = Color.white; } if (ropePosition != rope.transform.position) { ropePosition = rope.transform.position; UpdateEndsJoints(rope); } }
void OnSceneGUI() { PointManager.Instance = (target as PointManager); Vector3[] localPoints = PointManager.Instance.nodes.ToArray(); Vector3[] worldPoints = new Vector3[PointManager.Instance.nodes.Count]; for (int i = 0; i < worldPoints.Length; i++) { worldPoints[i] = PointManager.Instance.transform.TransformPoint(localPoints[i]); } DrawPoints(worldPoints); DrawNodes(worldPoints); #region AddPoint if (Event.current.shift) { Vector3 mousePos = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition).origin; Vector3 pointLocalMousePos = PointManager.Instance.transform.InverseTransformPoint(mousePos); Vector3 nodeOnPoly = HandleUtility.ClosestPointToPolyLine(worldPoints); float handleSize = HandleUtility.GetHandleSize(nodeOnPoly); int nodeIndex = FindNodeIndex(worldPoints, nodeOnPoly); Handles.DrawLine(worldPoints[nodeIndex - 1], mousePos); Handles.DrawLine(worldPoints[nodeIndex], mousePos); if (Handles.Button(mousePos, Quaternion.identity, handleSize * .1f, handleSize, HandleFunc)) { pointLocalMousePos.y = 1f; Undo.RecordObject(PointManager.Instance, "InsertNode"); PointManager.Instance.nodes.Insert(nodeIndex, pointLocalMousePos); Event.current.Use(); } } #endregion #region DeletePoint if (Event.current.control) { int indexToDelete = FindeNearestNodeToMouse(worldPoints); Handles.color = Color.red; float handleSize = HandleUtility.GetHandleSize(worldPoints[0]); if (Handles.Button(worldPoints[indexToDelete], Quaternion.identity, handleSize * 0.09f, handleSize, DeleteHandle)) { Undo.RecordObject(PointManager.Instance, "Remove Node"); PointManager.Instance.nodes.RemoveAt(indexToDelete); indexToDelete = -1; Event.current.Use(); } Handles.color = Color.white; } #endregion }
/// <summary> /// Draws the glyph add-point-to-edge handles. /// </summary> public void DrawGlyphEdgeHandles() { serializedObject.Update(); handleSize = HandleUtility.GetHandleSize(Vector3.zero) * 0.04f; if (strokes != null) { SerializedProperty child = strokes.Copy(); child.Next(true); float bestDist = float.PositiveInfinity; SerializedProperty bestPoint = null; foreach (SerializedProperty childStroke in child) { SerializedProperty childArray = childStroke.Copy(); childArray.Next(true); childArray.Next(true); SerializedProperty prev, curr = childArray.GetArrayElementAtIndex(0); for (int p = 1; p < childArray.arraySize; p++) { prev = curr; curr = childArray.GetArrayElementAtIndex(p); float dist = HandleUtility.DistanceToLine(prev.vector2Value, curr.vector2Value); if (dist < bestDist) { bestDist = dist; bestPoint = prev; } } } if (bestDist < 5f) { SerializedProperty nextPoint = bestPoint.Copy(); nextPoint.Next(false); Vector3 closestPoint = HandleUtility.ClosestPointToPolyLine(bestPoint.vector2Value, nextPoint.vector2Value); if (Handles.Button(closestPoint, Quaternion.identity, handleSize, handleSize, Handles.DotHandleCap)) { //dup and move if (bestPoint.DuplicateCommand()) { bestPoint.Next(false); bestPoint.vector2Value = (Vector2)closestPoint; } } } } serializedObject.ApplyModifiedProperties(); }
private void DisplayCollider() { Event e = Event.current; if (Tileset.SelectedBrushId != Tileset.k_BrushId_Default) { EditorGUILayout.LabelField("Brush tile editing not allowed", EditorStyles.boldLabel); return; } bool isMultiselection = Tileset.TileSelection != null; bool saveChanges = false; Tile selectedTile = isMultiselection ? Tileset.Tiles[(int)(Tileset.TileSelection.selectionData[0] & Tileset.k_TileDataMask_TileId)] : Tileset.SelectedTile; if (e.type == EventType.MouseDown) { m_isDragging = true; if (selectedTile.collData.vertices != null) { m_savedVertexData = new Vector2[selectedTile.collData.vertices.Length]; selectedTile.collData.vertices.CopyTo(m_savedVertexData, 0); } } else if (e.type == EventType.MouseUp) { m_isDragging = false; } Tileset.BackgroundColor = EditorGUILayout.ColorField(Tileset.BackgroundColor); if (m_prevBgColor != Tileset.BackgroundColor || Styles.Instance.colliderBgStyle.normal.background == null) { m_prevBgColor = Tileset.BackgroundColor; if (Styles.Instance.colliderBgStyle.normal.background == null) { Styles.Instance.colliderBgStyle.normal.background = new Texture2D(1, 1) { hideFlags = HideFlags.DontSave } } ; Styles.Instance.colliderBgStyle.normal.background.SetPixel(0, 0, Tileset.BackgroundColor); Styles.Instance.colliderBgStyle.normal.background.Apply(); } float aspectRatio = Tileset.TilePxSize.x / Tileset.TilePxSize.y; float padding = 2; // pixel size of the border around the tile //Rect rCollArea = GUILayoutUtility.GetRect(1, 1, GUILayout.Width(EditorGUIUtility.currentViewWidth), GUILayout.Height(EditorGUIUtility.currentViewWidth / aspectRatio)); Rect rCollArea = GUILayoutUtility.GetRect(1, 1, GUILayout.ExpandWidth(true), GUILayout.ExpandHeight(true)); GUI.BeginGroup(rCollArea, Styles.Instance.colliderBgStyle); if (e.type == EventType.Repaint) { float pixelSize = rCollArea.width / (Tileset.TilePxSize.x + 2 * padding); m_mousePos = e.mousePosition; m_rTile = new Rect(padding * pixelSize, padding * pixelSize, rCollArea.width - 2 * padding * pixelSize, (rCollArea.width / aspectRatio) - 2 * padding * pixelSize); m_rTile.height = Mathf.Min(m_rTile.height, rCollArea.height - 2 * padding * pixelSize); m_rTile.width = (m_rTile.height * aspectRatio); } GUI.color = new Color(1f, 1f, 1f, 0.1f); GUI.DrawTexture(m_rTile, EditorGUIUtility.whiteTexture); GUI.color = Color.white; if (isMultiselection) { foreach (uint tileData in Tileset.TileSelection.selectionData) { int tileId = (int)(tileData & Tileset.k_TileDataMask_TileId); Tile tile = (tileId != Tileset.k_TileId_Empty) ? Tileset.Tiles[tileId] : null; if (tile != null) { GUI.color = new Color(1f, 1f, 1f, 1f / Tileset.TileSelection.selectionData.Count); GUI.DrawTextureWithTexCoords(m_rTile, Tileset.AtlasTexture, tile.uv); } } GUI.color = Color.white; } else { GUI.DrawTextureWithTexCoords(m_rTile, Tileset.AtlasTexture, selectedTile.uv); } Color savedHandleColor = Handles.color; if (selectedTile.collData.type != eTileCollider.None) { Vector2[] collVertices = selectedTile.collData.type == eTileCollider.Full ? s_fullCollTileVertices : selectedTile.collData.vertices; if (collVertices == null || collVertices.Length == 0) { collVertices = selectedTile.collData.vertices = new Vector2[s_fullCollTileVertices.Length]; Array.Copy(s_fullCollTileVertices, collVertices, s_fullCollTileVertices.Length); EditorUtility.SetDirty(Tileset); } // Fix and snap positions for (int i = 0; i < collVertices.Length; ++i) { Vector2 s0 = collVertices[i]; s0.x = Mathf.Clamp01(Mathf.Round(s0.x * Tileset.TilePxSize.x) / Tileset.TilePxSize.x); s0.y = Mathf.Clamp01(Mathf.Round(s0.y * Tileset.TilePxSize.y) / Tileset.TilePxSize.y); collVertices[i] = s0; } // Draw edges Vector3[] polyEdges = new Vector3[collVertices.Length + 1]; for (int i = 0; i < collVertices.Length; ++i) { Vector2 s0 = collVertices[i]; s0.x = m_rTile.x + m_rTile.width * s0.x; s0.y = m_rTile.yMax - m_rTile.height * s0.y; Vector2 s1 = collVertices[(i + 1) % collVertices.Length]; s1.x = m_rTile.x + m_rTile.width * s1.x; s1.y = m_rTile.yMax - m_rTile.height * s1.y; polyEdges[i] = s0; polyEdges[i + 1] = s1; Handles.color = Color.green; Handles.DrawLine(s0, s1); //Draw normals { Handles.color = Color.white; Vector3 normPos = (s0 + s1) / 2f; Handles.DrawLine(normPos, normPos + Vector3.Cross(s1 - s0, Vector3.forward).normalized *m_rTile.yMin); } Handles.color = savedHandleColor; } float pixelSize = m_rTile.width / Tileset.TilePxSize.x; if (selectedTile.collData.type == eTileCollider.Polygon) { bool isAddingVertexOn = !m_isDragging && e.shift && m_activeVertexIdx == -1; bool isRemovingVertexOn = !m_isDragging && ((Application.platform == RuntimePlatform.OSXEditor)? e.command : e.control) && collVertices.Length > 3; if (isRemovingVertexOn && m_activeVertexIdx != -1 && e.type == EventType.MouseUp) { selectedTile.collData.vertices = new Vector2[collVertices.Length - 1]; for (int i = 0, j = 0; i < collVertices.Length; ++i) { if (i == m_activeVertexIdx) { continue; } selectedTile.collData.vertices[j] = collVertices[i]; ++j; } collVertices = selectedTile.collData.vertices; m_activeVertexIdx = -1; } float minDist = float.MaxValue; if (!m_isDragging) { m_activeVertexIdx = -1; } for (int i = 0; i < collVertices.Length; ++i) { Vector2 s0 = collVertices[i]; s0.x = m_rTile.x + m_rTile.width * s0.x; s0.y = m_rTile.yMax - m_rTile.height * s0.y; if (m_isDragging) { if (i == m_activeVertexIdx) { s0 = m_mousePos; s0 -= m_rTile.position; s0.x = Mathf.Clamp(Mathf.Round(s0.x / pixelSize) * pixelSize, 0, m_rTile.width); s0.y = Mathf.Clamp(Mathf.Round(s0.y / pixelSize) * pixelSize, 0, m_rTile.height); s0 += m_rTile.position; collVertices[i].x = Mathf.Clamp01((s0.x - m_rTile.x) / m_rTile.width); collVertices[i].y = Mathf.Clamp01((s0.y - m_rTile.yMax) / -m_rTile.height); } } else { float dist = Vector2.Distance(m_mousePos, s0); if (dist <= minDist && dist < Styles.Instance.collVertexHandleStyle.normal.background.width) { minDist = dist; m_activeVertexIdx = i; } } if (e.type == EventType.Repaint) { if (i == m_activeVertexIdx) { Styles.Instance.vertexCoordStyle.fontSize = (int)(Mathf.Min(10f, m_rTile.yMin / 2f)); GUI.Label(new Rect(0, 0, m_rTile.width, m_rTile.yMin), Vector2.Scale(collVertices[i], Tileset.TilePxSize).ToString(), Styles.Instance.vertexCoordStyle); } GUI.color = m_activeVertexIdx == i ? (isRemovingVertexOn ? Color.red : Color.cyan) : new Color(0.7f, 0.7f, 0.7f, 0.8f); Styles.Instance.collVertexHandleStyle.Draw(new Rect(s0.x - Styles.Instance.collVertexHandleStyle.normal.background.width / 2, s0.y - Styles.Instance.collVertexHandleStyle.normal.background.height / 2, 1, 1), i.ToString(), false, false, false, false); GUI.color = Color.white; } } if (isAddingVertexOn) { int segmentIdx; Vector2 newVertexPos = ClosestPointToPolyLine(polyEdges, out segmentIdx); if (e.type == EventType.MouseUp) { selectedTile.collData.vertices = new Vector2[collVertices.Length + 1]; segmentIdx = (segmentIdx + 1) % selectedTile.collData.vertices.Length; for (int i = 0, j = 0; i < selectedTile.collData.vertices.Length; ++i) { if (segmentIdx == i) { newVertexPos.x = Mathf.Clamp(Mathf.Round(newVertexPos.x / pixelSize) * pixelSize, m_rTile.x, m_rTile.xMax); newVertexPos.y = Mathf.Clamp(Mathf.Round(newVertexPos.y / pixelSize) * pixelSize, m_rTile.y, m_rTile.yMax); selectedTile.collData.vertices[i].x = Mathf.Clamp01((newVertexPos.x - m_rTile.x) / m_rTile.width); selectedTile.collData.vertices[i].y = Mathf.Clamp01((newVertexPos.y - m_rTile.yMax) / -m_rTile.height); } else { selectedTile.collData.vertices[i] = collVertices[j]; ++j; } } collVertices = selectedTile.collData.vertices; m_activeVertexIdx = -1; } else if (e.type == EventType.Repaint) { GUI.color = new Color(0.7f, 0.7f, 0.7f, 0.8f); Styles.Instance.collVertexHandleStyle.Draw(new Rect(newVertexPos.x - Styles.Instance.collVertexHandleStyle.normal.background.width / 2, newVertexPos.y - Styles.Instance.collVertexHandleStyle.normal.background.height / 2, 1, 1), segmentIdx.ToString(), false, false, false, false); GUI.color = Color.white; } } } if (e.type == EventType.MouseUp) { saveChanges = true; //remove duplicated vertex selectedTile.collData.vertices = selectedTile.collData.vertices.Distinct().ToArray(); if (selectedTile.collData.vertices.Length <= 2) { selectedTile.collData.vertices = m_savedVertexData; } } } GUI.EndGroup(); if (GUILayout.Button("Reverse Normals")) { selectedTile.collData.vertices = selectedTile.collData.vertices.Reverse().ToArray(); } EditorGUILayout.Space(); string helpInfo = //"Using Polygon collider:" + "\n" + " - Click and drag over a vertex to move it" + "\n" + " - Hold Shift + Click for adding a new vertex" + "\n" + " - Hold " + ((Application.platform == RuntimePlatform.OSXEditor)? "Command" : "Ctrl") + " + Click for removing a vertex. (should be more than 3)" + "\n" + " - Check the normals for each edge. The normal is displayed in the collision side" + "\n" + ""; s_showHelp = EditorGUILayout.Foldout(s_showHelp, "Help"); if (s_showHelp) { EditorGUILayout.HelpBox(helpInfo, MessageType.Info); } //+++ Collider Settings float savedLabelWidth = EditorGUIUtility.labelWidth; EditorGUIUtility.labelWidth = 40; if (isMultiselection) { EditorGUILayout.LabelField("* Multi-selection Edition", EditorStyles.boldLabel); } EditorGUILayout.BeginHorizontal(GUILayout.MinWidth(140)); { EditorGUILayout.LabelField("Collider Data", EditorStyles.boldLabel); if (GUILayout.Button("Copy", GUILayout.Width(50))) { m_copiedColliderData = selectedTile.collData.Clone(); } if (GUILayout.Button("Paste", GUILayout.Width(50))) { selectedTile.collData = m_copiedColliderData.Clone(); saveChanges = true; } } EditorGUILayout.EndHorizontal(); EditorGUILayout.Space(); EditorGUIUtility.labelWidth = 100; EditorGUI.BeginChangeCheck(); //selectedTile.collData.type = (eTileCollider)EditorGUILayout.EnumPopup("Collider Type", selectedTile.collData.type); EditorGUILayout.LabelField("Collider Type:", EditorStyles.boldLabel); EditorGUI.indentLevel += 2; string[] tileColliderNames = System.Enum.GetNames(typeof(eTileCollider)); selectedTile.collData.type = (eTileCollider)GUILayout.Toolbar((int)selectedTile.collData.type, tileColliderNames); EditorGUI.indentLevel -= 2; saveChanges |= EditorGUI.EndChangeCheck(); EditorGUIUtility.labelWidth = savedLabelWidth; //--- //Save changes if (saveChanges) { if (isMultiselection) { for (int i = 0; i < Tileset.TileSelection.selectionData.Count; ++i) { Tileset.Tiles[(int)(Tileset.TileSelection.selectionData[i] & Tileset.k_TileDataMask_TileId)].collData = selectedTile.collData.Clone(); } } EditorUtility.SetDirty(Tileset); } } /// <summary> // Get the point on a polyline (in 3D space) which is closest to the current // mouse position. And returns the segment index ( the vertex index of the segment with the closest point ) /// </summary> /// <param name="vertices"></param> /// <param name="closedSegmentIdx"></param> /// <returns></returns> Vector3 ClosestPointToPolyLine(Vector3[] vertices, out int closedSegmentIdx) { float minDist = float.MaxValue; closedSegmentIdx = 0; for (int i = 0; i < vertices.Length - 1; ++i) { float dist = HandleUtility.DistanceToLine(vertices[i], vertices[i + 1]); if (dist < minDist) { minDist = dist; closedSegmentIdx = i; } } return(HandleUtility.ClosestPointToPolyLine(vertices)); }
private void DoTools() { if (Event.current.rawType == EventType.KeyDown && Event.current.isKey && !isDown) { tool = curve.tool; KeyCode key = Event.current.keyCode; if (key == KeyCode.A) { curve.tool = PaintTools.Add; } else if (key == KeyCode.D) { curve.tool = PaintTools.Remove; } else if (key == KeyCode.I) { curve.tool = PaintTools.Insert; } isDown = true; EditorUtility.SetDirty(curve); Event.current.Use(); } else if (Event.current.rawType == EventType.KeyUp) { curve.tool = tool; isDown = false; EditorUtility.SetDirty(curve); Event.current.Use(); } switch (curve.tool) { case PaintTools.Add: EditorGUIUtility.AddCursorRect(new Rect(0, 0, Screen.width, Screen.height), MouseCursor.ArrowPlus); SceneView.RepaintAll(); if (Event.current.type == EventType.MouseDown && Event.current.button == 0) { GUIUtility.hotControl = 0; Plane plane = new Plane(Camera.current.transform.forward, Vector3.zero); float dist = 0f; Ray ray = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition); if (plane.Raycast(ray, out dist)) { Vector3 newPosition = ray.GetPoint(dist); curve.AddPointAt(curve.transform.InverseTransformPoint(newPosition)); curve.SendMessage("OnRectTransformDimensionsChange", SendMessageOptions.DontRequireReceiver); EditorUtility.SetDirty(curve); } Event.current.Use(); } break; case PaintTools.Insert: int limit = curve.resolution + 1; float _res = curve.resolution; if (curve.count > 1) { for (int index = 0; index < curve.count - 1; index++) { BezierPoint p1 = curve[index]; BezierPoint p2 = curve[index + 1]; Vector3 lastPoint = p1.localPosition; Vector3 currentPoint = Vector3.zero; for (int i = 1; i < limit; i++) { currentPoint = BezierCurve.GetPoint(p1, p2, i / _res); if (HandleUtility.DistanceToLine(curve.transform.TransformPoint(currentPoint), curve.transform.TransformPoint(lastPoint)) < 2f && Vector2.Distance(Event.current.mousePosition, HandleUtility.WorldToGUIPoint(curve.transform.TransformPoint(p1.localPosition))) > 5f && Vector2.Distance(Event.current.mousePosition, HandleUtility.WorldToGUIPoint(curve.transform.TransformPoint(p2.localPosition))) > 5f) { EditorGUIUtility.AddCursorRect(new Rect(0, 0, Screen.width, Screen.height), MouseCursor.ArrowPlus); SceneView.RepaintAll(); if (Event.current.type == EventType.MouseDown) { GUIUtility.hotControl = 0; curve.AddPointAt(index + 1, HandleUtility.ClosestPointToPolyLine(lastPoint, currentPoint)); curve.SendMessage("OnRectTransformDimensionsChange", SendMessageOptions.DontRequireReceiver); EditorUtility.SetDirty(curve); Event.current.Use(); } } lastPoint = currentPoint; } } } break; case PaintTools.Remove: if (curve.count > 2) { for (int index = 0; index < curve.count; index++) { BezierPoint p = curve[index]; Vector2 guiPoint = HandleUtility.WorldToGUIPoint(curve.transform.TransformPoint(p.localPosition)); if (Vector2.Distance(Event.current.mousePosition, guiPoint) < 5f) { EditorGUIUtility.AddCursorRect(new Rect(0, 0, Screen.width, Screen.height), MouseCursor.ArrowMinus); SceneView.RepaintAll(); if (Event.current.type == EventType.MouseDown) { GUIUtility.hotControl = 0; curve.RemovePoint(p); curve.SendMessage("OnRectTransformDimensionsChange", SendMessageOptions.DontRequireReceiver); EditorUtility.SetDirty(curve); Event.current.Use(); } } } } break; } }
/// <summary> /// Construct & display the curve from DragPointsHandler control points /// Find the curve traveller position along the curve /// </summary> /// /// <remarks> /// Will use the DragPointExposure from the handler's item to display slingshot segments accordingly /// Will update handler's curve traveller position and control point base index for point insertion /// </remarks> private void DisplayCurve() { List <Vector3>[] controlPointsSegments = new List <Vector3> [_handler.ControlPoints.Count].Select(item => new List <Vector3>()).ToArray(); // Display Curve & handle curve traveller if (_handler.ControlPoints.Count > 1) { var transformedDPoints = new List <DragPointData>(); foreach (var controlPoint in _handler.ControlPoints) { var newDp = new DragPointData(controlPoint.DragPoint) { Center = controlPoint.WorldPos.ToVertex3D() }; transformedDPoints.Add(newDp); } var vAccuracy = Vector3.one; vAccuracy = _handler.Transform.localToWorldMatrix.MultiplyVector(vAccuracy); var accuracy = Mathf.Abs(vAccuracy.x * vAccuracy.y * vAccuracy.z); accuracy *= HandleUtility.GetHandleSize(_handler.CurveTravellerPosition) * ControlPoint.ScreenRadius; var vVertex = DragPoint.GetRgVertex <RenderVertex3D, CatmullCurve3DCatmullCurveFactory>( transformedDPoints.ToArray(), _handler.DragPointInspector.PointsAreLooping, accuracy ); if (vVertex.Length > 0) { // Fill Control points paths ControlPoint currentControlPoint = null; foreach (var v in vVertex) { if (v.IsControlPoint) { if (currentControlPoint != null) { controlPointsSegments[currentControlPoint.Index].Add(v.ToUnityVector3()); } currentControlPoint = _handler.ControlPoints.Find(cp => cp.WorldPos == v.ToUnityVector3()); } if (currentControlPoint != null) { controlPointsSegments[currentControlPoint.Index].Add(v.ToUnityVector3()); } } // close loop if needed if (_handler.DragPointInspector.PointsAreLooping) { controlPointsSegments[_handler.ControlPoints.Count - 1].Add(controlPointsSegments[0][0]); } // construct full path _pathPoints.Clear(); const float splitRatio = 0.1f; foreach (var controlPoint in _handler.ControlPoints) { // Split straight segments to avoid HandleUtility.ClosestPointToPolyLine issues ref var segments = ref controlPointsSegments[controlPoint.Index]; if (segments.Count == 2) { var dir = segments[1] - segments[0]; var dist = dir.magnitude; dir = Vector3.Normalize(dir); var newPath = new List <Vector3> { segments[0] }; for (var splitDist = dist * splitRatio; splitDist < dist; splitDist += dist * splitRatio) { newPath.Add(newPath[0] + dir * splitDist); } newPath.Add(segments[1]); segments = newPath; } _pathPoints.AddRange(segments); } _curveTravellerMoved = false; if (_pathPoints.Count > 1) { var newPos = HandleUtility.ClosestPointToPolyLine(_pathPoints.ToArray()); if ((newPos - _handler.CurveTravellerPosition).magnitude >= HandleUtility.GetHandleSize(_handler.CurveTravellerPosition) * ControlPoint.ScreenRadius * CurveTravellerSizeRatio * 0.1f) { _handler.CurveTravellerPosition = newPos; _curveTravellerMoved = true; } } // Render Curve with correct color regarding drag point properties & find curve section where the curve traveller is _handler.CurveTravellerControlPointIdx = -1; var minDist = float.MaxValue; foreach (var controlPoint in _handler.ControlPoints) { var segments = controlPointsSegments[controlPoint.Index].ToArray(); if (segments.Length > 1) { Handles.color = _handler.DragPointInspector.DragPointExposition.Contains(DragPointExposure.SlingShot) && controlPoint.DragPoint.IsSlingshot ? CurveSlingShotColor : CurveColor; Handles.DrawAAPolyLine(CurveWidth, segments); var closestToPath = HandleUtility.ClosestPointToPolyLine(segments); var dist = (closestToPath - _handler.CurveTravellerPosition).magnitude; if (dist < minDist) { minDist = dist; _handler.CurveTravellerControlPointIdx = controlPoint.Index; } } } } }
void OnSceneGUI() { EventType evt = Event.current.type; SkinMaker skin = (SkinMaker)target; List <Vector3> ctlp = skin.controlPoints.Select(v => v + skin.transform.position).ToList(); ctlp.Add(skin.controlPoints[0] + skin.transform.position); Vector3[] poly = ctlp.ToArray(); Handles.color = Color.gray; Handles.DrawAAPolyLine(poly); Vector3 p = HandleUtility.ClosestPointToPolyLine(poly); int selCtrl = -1; Handles.color = Color.green; for (int i = 0; i < skin.controlPoints.Length; i++) { Vector3 hp = Handles.FreeMoveHandle(skin.transform.position + skin.controlPoints[i], Quaternion.identity, 0.05f, Vector3.zero, Handles.RectangleCap); if (Vector3.Distance(hp, p) < 0.05f) { selCtrl = i; } hp = hp - skin.transform.position; skin.controlPoints[i] = new Vector3(Mathf.Clamp(hp.x, -1, 1), Mathf.Clamp(hp.y, -1, 1), Mathf.Clamp(hp.z, -1, 1)); } if (Event.current.shift) { Handles.color = Color.blue; Handles.DrawWireDisc(p, Vector3.forward, 0.05f); if (evt == EventType.mouseDown) { Undo.RecordObject(skin, "Add handle"); for (int i = 0; i < poly.Length - 1; i++) { float d = (float)System.Math.Round(HandleUtility.DistancePointLine(p, ctlp[i], ctlp[i + 1]), 4); if (d == 0) { ctlp = new List <Vector3>(skin.controlPoints); ctlp.Insert(i + 1, p - skin.transform.position); skin.controlPoints = ctlp.ToArray(); } } } } else if (Event.current.control) { if (evt == EventType.mouseDown) { Undo.RecordObject(skin, "Remove handle"); if (selCtrl != -1) { if (skin.controlPoints.Length > 4) { ctlp = new List <Vector3>(skin.controlPoints); ctlp.RemoveAt(selCtrl); skin.controlPoints = ctlp.ToArray(); } else { EditorUtility.DisplayDialog("Cannot delete control point", "There have to be at least 4 control points.", "Ok"); } } } } }
private void DisplayCollider() { Event e = Event.current; if (tileSet.selected_tileSetBrushId != TileSetConst.TileSetBrushId_Default) { EditorGUILayout.LabelField("tileSetBrush不能被编辑", EditorStyles.boldLabel); return; } bool is_multi_selection = tileSet.tileSelection != null; bool is_save_changes = false; Tile selected_tile = is_multi_selection ? tileSet.tile_list[TileSetUtil.GetTileIdFromTileData(tileSet.tileSelection.selection_tileData_list[0])] : tileSet.selected_tile; if (e.type == EventType.MouseDown) { is_dragging = true; if (selected_tile.tileColliderData.vertices != null) { saved_vertexs = new Vector2[selected_tile.tileColliderData.vertices.Length]; selected_tile.tileColliderData.vertices.CopyTo(saved_vertexs, 0); } } else if (e.type == EventType.MouseUp) { is_dragging = false; } //background_color tileSet.background_color = EditorGUILayout.ColorField(tileSet.background_color); if (pre_background_color != tileSet.background_color || GUIStyleConst.Scroll_Style.normal.background == null) { pre_background_color = tileSet.background_color; if (GUIStyleConst.Scroll_Style.normal.background == null) { GUIStyleConst.Scroll_Style.normal.background = new Texture2D(1, 1) { hideFlags = HideFlags.DontSave } } ; GUIStyleConst.Scroll_Style.normal.background.SetPixel(0, 0, tileSet.background_color); GUIStyleConst.Scroll_Style.normal.background.Apply(); } float aspect_ratio = tileSet.tile_pixel_size.x / tileSet.tile_pixel_size.y; //比例 float padding = 2; // pixel size of the border around the tile //画tile图 //包围tile_rect的rect Rect tile_parent_rect = GUILayoutUtility.GetRect(1, 1, GUILayout.ExpandWidth(true), GUILayout.ExpandHeight(true)); using (new GUIBeginGroupScope(tile_parent_rect, GUIStyleConst.Scroll_Style)) { if (e.type == EventType.Repaint) { float tile_pixel_size = tile_parent_rect.width / (tileSet.tile_pixel_size.x + 2 * padding);//2*padding是因为padding有左边和右边 mouse_pos = e.mousePosition; tile_rect = new Rect(padding * tile_pixel_size, padding * tile_pixel_size, tile_parent_rect.width - 2 * padding * tile_pixel_size, (tile_parent_rect.width / aspect_ratio) - 2 * padding * tile_pixel_size); tile_rect.height = Mathf.Min(tile_rect.height, tile_parent_rect.height - 2 * padding * tile_pixel_size); tile_rect.width = (tile_rect.height * aspect_ratio); } using (new GUIColorScope(new Color(1f, 1f, 1f, 0.1f))) { GUI.DrawTexture(tile_rect, EditorGUIUtility.whiteTexture); } if (is_multi_selection) { foreach (uint tileData in tileSet.tileSelection.selection_tileData_list) { int tileId = TileSetUtil.GetTileIdFromTileData(tileData); Tile tile = tileSet.GetTile(tileId); if (tile != null) { GUI.color = new Color(1f, 1f, 1f, 1f / tileSet.tileSelection.selection_tileData_list.Count); GUI.DrawTextureWithTexCoords(tile_rect, tileSet.atlas_texture, tile.uv); } } GUI.color = Color.white; } else { GUI.DrawTextureWithTexCoords(tile_rect, tileSet.atlas_texture, selected_tile.uv); } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// Color saved_handle_color = Handles.color; if (selected_tile.tileColliderData.type != TileColliderType.None) { Vector2[] collider_vertices = selected_tile.tileColliderData.type == TileColliderType.Full ? TileConst.Full_Collider_Tile_Vertices : selected_tile.tileColliderData.vertices; if (collider_vertices == null || collider_vertices.Length == 0) { collider_vertices = selected_tile.tileColliderData.vertices = new Vector2[TileConst.Full_Collider_Tile_Vertices.Length]; Array.Copy(TileConst.Full_Collider_Tile_Vertices, collider_vertices, TileConst.Full_Collider_Tile_Vertices.Length); EditorUtility.SetDirty(tileSet); } // 将vertice的xy限制在[0,1]之间 for (int i = 0; i < collider_vertices.Length; ++i) { Vector2 collider_vertice = collider_vertices[i]; collider_vertice = collider_vertice.Snap2(tileSet.tile_pixel_size).ConvertElement(v => Mathf.Clamp01(v)); collider_vertices[i] = collider_vertice; } // 画边 draw edges Vector3[] poly_edges = new Vector3[collider_vertices.Length + 1]; for (int i = 0; i < collider_vertices.Length; ++i) { Vector2 collider_vertice = collider_vertices[i]; collider_vertice.x = tile_rect.x + tile_rect.width * collider_vertice.x; collider_vertice.y = tile_rect.yMax - tile_rect.height * collider_vertice.y; Vector2 collider_vertice_next = collider_vertices[(i + 1) % collider_vertices.Length]; collider_vertice_next.x = tile_rect.x + tile_rect.width * collider_vertice_next.x; collider_vertice_next.y = tile_rect.yMax - tile_rect.height * collider_vertice_next.y; poly_edges[i] = collider_vertice; poly_edges[i + 1] = collider_vertice_next; //画边 Handles.color = Color.green; Handles.DrawLine(collider_vertice, collider_vertice_next); //画边上的法线 Draw normals Handles.color = Color.white; Vector3 normal_pos = (collider_vertice + collider_vertice_next) / 2f; Handles.DrawLine(normal_pos, normal_pos + Vector3.Cross(collider_vertice_next - collider_vertice, Vector3.forward).normalized *tile_rect.yMin); Handles.color = saved_handle_color; } float pixel_size = tile_rect.width / tileSet.tile_pixel_size.x; if (selected_tile.tileColliderData.type == TileColliderType.Polygon) { bool is_adding_vertex_on = !is_dragging && e.shift && active_vertex_index == -1; bool is_removing_vertex_on = !is_dragging && ((Application.platform == RuntimePlatform.OSXEditor) ? e.command : e.control) && collider_vertices.Length > 3; //删除顶点 if (is_removing_vertex_on && active_vertex_index != -1 && e.type == EventType.MouseUp) { selected_tile.tileColliderData.vertices = new Vector2[collider_vertices.Length - 1]; for (int i = 0, j = 0; i < collider_vertices.Length; ++i) { if (i == active_vertex_index) { continue; } selected_tile.tileColliderData.vertices[j] = collider_vertices[i]; ++j; } collider_vertices = selected_tile.tileColliderData.vertices; active_vertex_index = -1; } float min_distance = float.MaxValue; if (!is_dragging) { active_vertex_index = -1; } for (int i = 0; i < collider_vertices.Length; ++i) { Vector2 collider_vertice = collider_vertices[i]; collider_vertice.x = tile_rect.x + tile_rect.width * collider_vertice.x; collider_vertice.y = tile_rect.yMax - tile_rect.height * collider_vertice.y; if (is_dragging) { if (i == active_vertex_index) { collider_vertice = mouse_pos; collider_vertice -= tile_rect.position; collider_vertice.x = Mathf.Clamp(Mathf.Round(collider_vertice.x / pixel_size) * pixel_size, 0, tile_rect.width); collider_vertice.y = Mathf.Clamp(Mathf.Round(collider_vertice.y / pixel_size) * pixel_size, 0, tile_rect.height); collider_vertice += tile_rect.position; collider_vertices[i].x = Mathf.Clamp01((collider_vertice.x - tile_rect.x) / tile_rect.width); collider_vertices[i].y = Mathf.Clamp01((collider_vertice.y - tile_rect.yMax) / -tile_rect.height); } } else { float distance = Vector2.Distance(mouse_pos, collider_vertice); //distance < GUIStyleConst.Collider_Vertex_Handle_Style.normal.background.width是为了限定少于多少距离(该顶点与mouse_pos的距离)的时候才选中该顶点 if (distance <= min_distance && distance < GUIStyleConst.Collider_Vertex_Handle_Style.normal.background.width) { min_distance = distance; active_vertex_index = i; } } //画顶点 if (e.type == EventType.Repaint) { //画左上角的坐标 if (i == active_vertex_index) { GUIStyleConst.VertexCoord_Style.fontSize = (int)(Mathf.Min(12f, tile_rect.yMin / 2f)); GUI.Label(new Rect(0, 0, tile_rect.width, tile_rect.yMin), Vector2.Scale(collider_vertices[i], tileSet.tile_pixel_size).ToString(), GUIStyleConst.VertexCoord_Style); } GUI.color = active_vertex_index == i ? (is_removing_vertex_on ? Color.red : Color.cyan) : new Color(0.7f, 0.7f, 0.7f, 0.8f); GUIStyleConst.Collider_Vertex_Handle_Style.Draw(new Rect(collider_vertice.x - GUIStyleConst.Collider_Vertex_Handle_Style.normal.background.width / 2, collider_vertice.y - GUIStyleConst.Collider_Vertex_Handle_Style.normal.background.height / 2, 1, 1), i.ToString(), false, false, false, false); GUI.color = Color.white; } } //添加顶点 if (is_adding_vertex_on) { //线段index int segment_index; Vector2 new_vertex_pos = ClosestPointToPolyLine(poly_edges, out segment_index); if (e.type == EventType.MouseUp) { selected_tile.tileColliderData.vertices = new Vector2[collider_vertices.Length + 1]; segment_index = (segment_index + 1) % selected_tile.tileColliderData.vertices.Length; for (int i = 0, j = 0; i < selected_tile.tileColliderData.vertices.Length; ++i) { if (segment_index == i) { new_vertex_pos.x = Mathf.Clamp(Mathf.Round(new_vertex_pos.x / pixel_size) * pixel_size, tile_rect.x, tile_rect.xMax); new_vertex_pos.y = Mathf.Clamp(Mathf.Round(new_vertex_pos.y / pixel_size) * pixel_size, tile_rect.y, tile_rect.yMax); selected_tile.tileColliderData.vertices[i].x = Mathf.Clamp01((new_vertex_pos.x - tile_rect.x) / tile_rect.width); selected_tile.tileColliderData.vertices[i].y = Mathf.Clamp01((new_vertex_pos.y - tile_rect.yMax) / -tile_rect.height); } else { selected_tile.tileColliderData.vertices[i] = collider_vertices[j]; ++j; } } collider_vertices = selected_tile.tileColliderData.vertices; active_vertex_index = -1; } else if (e.type == EventType.Repaint) { //添加顶点中移动鼠标,透明动态显示当前将要新增顶点的位置 GUI.color = new Color(0.7f, 0.7f, 0.7f, 0.8f); GUIStyleConst.Collider_Vertex_Handle_Style.Draw(new Rect(new_vertex_pos.x - GUIStyleConst.Collider_Vertex_Handle_Style.normal.background.width / 2, new_vertex_pos.y - GUIStyleConst.Collider_Vertex_Handle_Style.normal.background.height / 2, 1, 1), segment_index.ToString(), false, false, false, false); GUI.color = Color.white; } } } if (e.type == EventType.MouseUp) { is_save_changes = true; //remove duplicated vertex selected_tile.tileColliderData.vertices = selected_tile.tileColliderData.vertices.Distinct().ToArray(); if (selected_tile.tileColliderData.vertices.Length <= 2) { selected_tile.tileColliderData.vertices = saved_vertexs; } //snap vertex positions selected_tile.tileColliderData.SnapVertices(tileSet); } } } if (GUILayout.Button("反转法线")) { selected_tile.tileColliderData.vertices.Reverse(); } EditorGUILayout.Space(); string helpInfo = " - 移动:点击图中的顶点并移动它的位置" + "\n" + " - 添加:按住Shift并点击鼠标进行添加顶点" + "\n" + " - 删除:按住Ctrl并且点击顶点进行删除顶点 (should be more than 3)"; EditorGUILayout.HelpBox(helpInfo, MessageType.Info); // Collider Settings float saved_label_width = EditorGUIUtility.labelWidth; EditorGUIUtility.labelWidth = 40; if (is_multi_selection) { EditorGUILayout.LabelField("* Multi-selection Edition", EditorStyles.boldLabel); } using (new EditorGUILayoutBeginHorizontalScope(GUILayout.MinWidth(140))) { EditorGUILayout.LabelField("Collider Data", EditorStyles.boldLabel); if (GUILayout.Button("Copy", GUILayout.Width(50))) { copied_colliderData = selected_tile.tileColliderData.Clone(); } if (GUILayout.Button("Paste", GUILayout.Width(50))) { selected_tile.tileColliderData = copied_colliderData.Clone(); is_save_changes = true; } } EditorGUILayout.Space(); using (var check = new EditorGUIBeginChangeCheckScope()) { EditorGUIUtility.labelWidth = 100; EditorGUILayout.LabelField("Collider Type:", EditorStyles.boldLabel); using (new EditorGUIIndentLevelScope(2)) { string[] tile_collider_names = Enum.GetNames(typeof(TileColliderType)); selected_tile.tileColliderData.type = (TileColliderType)GUILayout.Toolbar((int)selected_tile.tileColliderData.type, tile_collider_names); } EditorGUIUtility.labelWidth = saved_label_width; is_save_changes |= check.IsChanged; } //Save changes if (is_save_changes) { if (is_multi_selection) { for (int i = 0; i < tileSet.tileSelection.selection_tileData_list.Count; ++i) { tileSet.tile_list[TileSetUtil.GetTileIdFromTileData(tileSet.tileSelection.selection_tileData_list[i])].tileColliderData = selected_tile.tileColliderData.Clone(); } } EditorUtility.SetDirty(tileSet); //Refresh selected tileMap TileMap selected_tileMap = Selection.activeGameObject ? Selection.activeGameObject.GetComponent <TileMap>() : null; if (selected_tileMap) { selected_tileMap.Refresh(false, true); } } } //获取polyline(vertices组成的线段)线段上的离当前mouse poistion最近的点 //Get the point on a polyline (in 3D space) which is closest to the current mouse position Vector3 ClosestPointToPolyLine(Vector3[] vertices, out int closest_segment_index) { float min_distance = float.MaxValue; closest_segment_index = 0; for (int i = 0; i < vertices.Length - 1; ++i) { float distance = HandleUtility.DistanceToLine(vertices[i], vertices[i + 1]); if (distance < min_distance) { min_distance = distance; closest_segment_index = i; } } return(HandleUtility.ClosestPointToPolyLine(vertices)); } }
void OnSceneGUI() { Shape shape = (Shape)target; if (!isEditingPolygon || shape.settings.shapeType != ShapeType.Polygon) { return; } // all the rest is for polygon editing if (Tools.current != Tool.None) { StopEditingPolygon(false); return; } HandleUtility.AddDefaultControl(GUIUtility.GetControlID(FocusType.Passive)); // draw the borders so the user knows where vertices should live DrawShapeBorders(shape); // get the existing verts Vector3[] oldVerts = shape.GetPolygonWorldVertices(); List <Vector3> verts = new List <Vector3>(oldVerts); bool hasMaxVerts = verts.Count == Shape.MaxPolygonVertices; // add the first vert at the end as well so Unity will draw it right etc verts.Add(verts[0]); // are we in delete mode? what color should handles be? Color pink = new Color(1, 0, 0.75f); bool deleteMode = false; if ((Event.current.control || Event.current.command) && verts.Count > 4) { Handles.color = Color.red; deleteMode = true; } else { Handles.color = pink; } // draw the shape Handles.DrawAAPolyLine(3f, verts.ToArray()); // drag handle result for getting info from our handles CustomHandles.DragHandleResult dhResult; // draw handles for each existing vert and check if they've been moved or clicked bool changed = false; for (int i = verts.Count - 2; i >= 0; i--) { Vector3 v = verts[i]; Vector3 newPos = CustomHandles.DragHandle(v, 0.05f * HandleUtility.GetHandleSize(v), Handles.DotCap, pink, out dhResult); if (deleteMode && dhResult == CustomHandles.DragHandleResult.LMBPress) { // the user clicked on the handle while in delete mode, so delete the vert verts.RemoveAt(i); changed = true; } else if (!deleteMode && newPos != v) { // the handle has been dragged, so move the vert to the new position verts[i] = new Vector2(newPos.x, newPos.y); changed = true; } } // check if the mouse is hovering over a space where we could add a new vert, // and draw it if so bool snapped = false; Vector3 closestPos = HandleUtility.ClosestPointToPolyLine(verts.ToArray()); float distance = HandleUtility.DistanceToPolyLine(verts.ToArray()); bool isCloseToLine = distance < 25; if (!changed && isCloseToLine && !hasMaxVerts && !deleteMode) { // todo - ClosestPointToPolyLine doesn't work very well in 3D... foreach (Vector3 v in verts) { // if close to an existing vert, we don't want to add a new one if (Vector2.Distance(HandleUtility.WorldToGUIPoint(closestPos), HandleUtility.WorldToGUIPoint(v)) < 15) { snapped = true; break; } } if (!snapped) { // not too close to an existing vert, so draw a new one. don't // use an actual handle cause we want to intercept nearby clicks // and not just clicks directly on the handle. Rect rect = new Rect(); float dim = 0.05f * HandleUtility.GetHandleSize(closestPos); rect.center = closestPos - new Vector3(dim, dim, 0); rect.size = new Vector2(dim * 2, dim * 2); Handles.color = Color.white; // remove the weird tint it does Handles.DrawSolidRectangleWithOutline(rect, Color.green, Color.clear); if (Event.current.type == EventType.MouseDown) { // the user has clicked the new vert, so add it for real // figure out which line segment it's on int lineStart = GetClosestLineToPoint(closestPos, verts); verts.Insert(lineStart + 1, closestPos); changed = true; } } } // something has been changed, so apply the new verts back to the shape if (changed) { // make sure to remove the duplicated last vert we added Undo.RecordObject(shape, "Edit Shapes2D Polygon Vertices"); shape.SetPolygonWorldVertices( verts.GetRange(0, verts.Count - 1).ToArray()); EditorUtility.SetDirty(target); } else { HandleUtility.Repaint(); // to draw the new vert placeholder handle if (Event.current.type == EventType.MouseDown && !isCloseToLine) { StopEditingPolygon(true); } } }
void OnSceneGUI() { //Tools.current = Tool.None; Event m_Event = Event.current; if (_editor.now_option == 1) { #region [시작시 점 위치] if (_editor.awake) { _editor.awake = false; _editor.waypoint[0] = _editor.transform.position; _editor.waypoint[1] = _editor.transform.position + new Vector3(1, 0, 0); _editor.waypoint[2] = _editor.transform.position + new Vector3(0.5f, 1, 0); _editor.start_pos = _editor.waypoint[0]; } else { _editor.transform.position = _editor.start_pos; } #endregion #region [점에 핸들달기] for (int i = 0; i < _editor.waypoint.Count; i++) { _editor.waypoint[i] = Handles.FreeMoveHandle(_editor.waypoint[i], Quaternion.identity, 0.05f, new Vector3(10, 10, 10), Handles.RectangleHandleCap); } #endregion #region [폴리곤 테두리 표시] Handles.color = Color.cyan; Vector3[] MouseLineVector; if (_editor.route_rotation) { MouseLineVector = new Vector3[_editor.waypoint.Count + 1]; for (int j = 0; j < _editor.waypoint.Count; j++) { MouseLineVector[j] = _editor.waypoint[j]; } MouseLineVector[_editor.waypoint.Count] = _editor.waypoint[0]; } else { MouseLineVector = new Vector3[_editor.waypoint.Count]; for (int j = 0; j < _editor.waypoint.Count; j++) { MouseLineVector[j] = _editor.waypoint[j]; } } Vector3 closestPoint = HandleUtility.ClosestPointToPolyLine(MouseLineVector); //Handles.DotHandleCap(0, closestPoint, Quaternion.identity, 0.05f, EventType.Repaint); #endregion #region [점 추가] if (m_Event.type == EventType.MouseDown && m_Event.button == 0) { //if(Vector3.Distance(Camera.main.ScreenToWorldPoint(new Vector3(m_Event.mousePosition.x, m_Event.mousePosition.y, -Camera.main.transform.position.z)),closestPoint) < 2f) // { Vector3 start = _editor.waypoint[0]; Vector3 end = _editor.waypoint[1]; float dis = HandleUtility.DistancePointLine(closestPoint, start, end); int num = 1; for (int i = 1; i < _editor.waypoint.Count; i++) { float distance = HandleUtility.DistancePointLine(closestPoint, _editor.waypoint[i - 1], _editor.waypoint[i]); if (distance < dis) { num = i; dis = distance; } } if (_editor.route_rotation) { float distance = HandleUtility.DistancePointLine(closestPoint, _editor.waypoint[_editor.waypoint.Count - 1], _editor.waypoint[0]); if (distance < dis) { num = _editor.waypoint.Count; } } _editor.waypoint.Insert(num, closestPoint); // } } #endregion } }
public static void Node_Add(SPData sPData) { SceneView.currentDrawingSceneView.Repaint(); EditorGUIUtility.AddCursorRect(Camera.current.pixelRect, MouseCursor.ArrowPlus); int nIndex = 0; string vertexPostion = "init"; Vector3 vert = Vector3.zero; if (sPData.Nodes.Count >= 2) { vert = HandleUtility.ClosestPointToPolyLine(sPData.Vertices.ToArray()); if (sPData.Close) { nIndex = BranchClosestNodeToVertex(sPData, vert); vertexPostion = "mid"; } else { if (Vector3.Distance(sPData.FirstNode.Point.position, vert) <= float.Epsilon) { nIndex = 0; vertexPostion = "beg"; } else if (Vector3.Distance(sPData.LastNode.Point.position, vert) <= float.Epsilon) { nIndex = sPData.Nodes.Count - 1; vertexPostion = "end"; } else { nIndex = BranchClosestNodeToVertex(sPData, vert); vertexPostion = "mid"; } } } // convert mouse position to vector3 world space Func <Vector2, Vector3> MousePos_To_Vector3 = delegate(Vector2 mousePosition) { float distance = 0.0f; RaycastHit Hit; Ray ray = new Ray(); Plane m_Plane; Vector3 hitPoint = Vector3.zero; ray = HandleUtility.GUIPointToWorldRay(mousePosition); if (Camera.current.transform.eulerAngles == new Vector3(0, 0, 0) || Camera.current.transform.eulerAngles == new Vector3(0, 180, 0)) { m_Plane = new Plane(Vector3.forward, Vector3.zero); } else if (Camera.current.transform.eulerAngles == new Vector3(90, 0, 0) || Camera.current.transform.eulerAngles == new Vector3(270, 0, 0)) { m_Plane = new Plane(Vector3.up, Vector3.zero); } else if (Camera.current.transform.eulerAngles == new Vector3(0, 90, 0) || Camera.current.transform.eulerAngles == new Vector3(0, 270, 0)) { m_Plane = new Plane(Vector3.right, Vector3.zero); } else { m_Plane = new Plane(Vector3.up, Vector3.zero); } if (Physics.Raycast(ray, out Hit)) { hitPoint = Hit.point; } else if (m_Plane.Raycast(ray, out distance)) { hitPoint = ray.GetPoint(distance); } return(hitPoint); }; // Add node to branch when click is performed Action <Vector3> Add_Node_Click = delegate(Vector3 pos) { if (Event.current.type == EventType.MouseDown && Event.current.button == 0) { Undo.RecordObject(sPData.SplinePlus, "Node added"); Func <string, Vector3, Quaternion, Transform, Transform> CreatePoint = delegate(string name, Vector3 Pos, Quaternion Rot, Transform Parent) { var Obj = new GameObject(name); Obj.hideFlags = HideFlags.HideInHierarchy; Obj.transform.position = Pos; Obj.transform.rotation = Rot; Obj.transform.parent = Parent; return(Obj.transform); }; var node = new Node(); node._Type = sPData.SplineSettings.NodeType; node.Point = CreatePoint("p", pos, Quaternion.identity, sPData.SplinePlus.gameObject.transform); node.Point1 = CreatePoint("p1", node.Point.position, Quaternion.identity, node.Point); node.Point2 = CreatePoint("p2", node.Point.position, Quaternion.identity, node.Point); if (sPData.Close) { SplinePlusAPI.Add_Node_At_Index(sPData, node, nIndex + 1); } else { if (vertexPostion == "beg" || vertexPostion == "init") { SplinePlusAPI.Add_Node_Beginning(sPData, node); } else if (vertexPostion == "end") { SplinePlusAPI.Add_Node_End(sPData, node); } else { SplinePlusAPI.Add_Node_At_Index(sPData, node, nIndex + 1); } } } }; //perform node adding when click event happens if (vertexPostion == "init") { var hitPoint = MousePos_To_Vector3(Event.current.mousePosition); Handles.color = Color.yellow; Handles.SphereHandleCap(0, hitPoint, Quaternion.identity, sPData.SplineSettings.GizmosSize * 2, EventType.Repaint); Add_Node_Click(hitPoint); } // node added to the beginning of the branch else if (vertexPostion == "beg") { var pos = MousePos_To_Vector3(Event.current.mousePosition); var node = sPData.Nodes[0]; Preview(sPData, node.Point.position, pos); Add_Node_Click(pos); } // node added to the end of the branch else if (vertexPostion == "end") { var pos = MousePos_To_Vector3(Event.current.mousePosition); var node = sPData.Nodes[sPData.Nodes.Count - 1]; Preview(sPData, node.Point.position, pos); Add_Node_Click(pos); } // node added in the middle of the branch else { Handles.color = Color.yellow; Handles.SphereHandleCap(0, vert, Quaternion.identity, sPData.SplineSettings.GizmosSize * 2, EventType.Repaint); Add_Node_Click(vert); } }
void OnSceneGUI() { // Tools.current = Tool.None; Event m_Event = Event.current; #region [시작시 점 위치] if (_editor.awake) { _editor.awake = false; _editor.camera_pos[0] = _editor.transform.position + new Vector3(+1, +1, 0); _editor.camera_pos[1] = _editor.transform.position + new Vector3(1, -1, 0); _editor.camera_pos[2] = _editor.transform.position + new Vector3(-1, -1, 0); _editor.camera_pos[3] = _editor.transform.position + new Vector3(-1, +1, 0); } #endregion #region [점에 핸들달기] for (int i = 0; i < _editor.camera_pos.Count; i++) { _editor.camera_pos[i] = Handles.FreeMoveHandle(_editor.camera_pos[i], Quaternion.identity, 0.05f, new Vector3(10, 10, 10), Handles.RectangleHandleCap); } #endregion #region [폴리곤 테두리 표시] Handles.color = Color.cyan; Vector3[] MouseLineVector; MouseLineVector = new Vector3[_editor.camera_pos.Count + 1]; for (int j = 0; j < _editor.camera_pos.Count; j++) { MouseLineVector[j] = _editor.camera_pos[j]; } MouseLineVector[_editor.camera_pos.Count] = _editor.camera_pos[0]; Vector3 closestPoint = HandleUtility.ClosestPointToPolyLine(MouseLineVector); #endregion #region [점 추가] if (m_Event.type == EventType.MouseDown && m_Event.button == 0) { Vector3 start = _editor.camera_pos[0]; Vector3 end = _editor.camera_pos[1]; float dis = HandleUtility.DistancePointLine(closestPoint, start, end); int num = 1; float distance = 0; for (int i = 1; i < _editor.camera_pos.Count; i++) { distance = HandleUtility.DistancePointLine(closestPoint, _editor.camera_pos[i - 1], _editor.camera_pos[i]); if (distance < dis) { num = i; dis = distance; } } distance = HandleUtility.DistancePointLine(closestPoint, _editor.camera_pos[_editor.camera_pos.Count - 1], _editor.camera_pos[0]); if (distance < dis) { num = _editor.camera_pos.Count; } _editor.camera_pos.Insert(num, closestPoint); } #endregion }