A game about forced loneliness, made by TACStudios
at master 778 lines 28 kB view raw
1using System; 2using Unity.Mathematics; 3using UnityEngine; 4 5namespace UnityEditor.U2D.Animation 6{ 7 internal class SpriteMeshController 8 { 9 const float k_SnapDistance = 10f; 10 11 struct EdgeIntersectionResult 12 { 13 public int startVertexIndex; 14 public int endVertexIndex; 15 public int intersectEdgeIndex; 16 public Vector2 endPosition; 17 } 18 19 SpriteMeshDataController m_SpriteMeshDataController = new(); 20 EdgeIntersectionResult m_EdgeIntersectionResult; 21 22 public ISpriteMeshView spriteMeshView { get; set; } 23 public BaseSpriteMeshData spriteMeshData { get; set; } 24 public ISelection<int> selection { get; set; } 25 public ICacheUndo cacheUndo { get; set; } 26 public ITriangulator triangulator { get; set; } 27 28 public bool disable { get; set; } 29 public Rect frame { get; set; } 30 31 public void OnGUI() 32 { 33 m_SpriteMeshDataController.spriteMeshData = spriteMeshData; 34 35 Debug.Assert(spriteMeshView != null); 36 Debug.Assert(spriteMeshData != null); 37 Debug.Assert(selection != null); 38 Debug.Assert(cacheUndo != null); 39 40 ValidateSelectionValues(); 41 42 spriteMeshView.selection = selection; 43 spriteMeshView.frame = frame; 44 45 EditorGUI.BeginDisabledGroup(disable); 46 47 spriteMeshView.BeginLayout(); 48 49 if (spriteMeshView.CanLayout()) 50 { 51 LayoutVertices(); 52 LayoutEdges(); 53 } 54 55 spriteMeshView.EndLayout(); 56 57 if (spriteMeshView.CanRepaint()) 58 { 59 DrawEdges(); 60 61 if (GUI.enabled) 62 { 63 PreviewCreateVertex(); 64 PreviewCreateEdge(); 65 PreviewSplitEdge(); 66 } 67 68 DrawVertices(); 69 } 70 71 72 HandleSplitEdge(); 73 HandleCreateEdge(); 74 HandleCreateVertex(); 75 76 EditorGUI.EndDisabledGroup(); 77 78 HandleSelectVertex(); 79 HandleSelectEdge(); 80 81 EditorGUI.BeginDisabledGroup(disable); 82 83 HandleMoveVertexAndEdge(); 84 85 EditorGUI.EndDisabledGroup(); 86 87 EditorGUI.BeginDisabledGroup(disable); 88 89 HandleRemoveVertices(); 90 91 spriteMeshView.DoRepaint(); 92 93 EditorGUI.EndDisabledGroup(); 94 } 95 96 void ValidateSelectionValues() 97 { 98 foreach (var index in selection.elements) 99 { 100 if (index >= spriteMeshData.vertexCount) 101 { 102 selection.Clear(); 103 break; 104 } 105 } 106 } 107 108 void LayoutVertices() 109 { 110 for (var i = 0; i < spriteMeshData.vertexCount; i++) 111 { 112 spriteMeshView.LayoutVertex(spriteMeshData.vertices[i], i); 113 } 114 } 115 116 void LayoutEdges() 117 { 118 for (var i = 0; i < spriteMeshData.edges.Length; i++) 119 { 120 var edge = spriteMeshData.edges[i]; 121 var startPosition = spriteMeshData.vertices[edge.x]; 122 var endPosition = spriteMeshData.vertices[edge.y]; 123 124 spriteMeshView.LayoutEdge(startPosition, endPosition, i); 125 } 126 } 127 128 void DrawEdges() 129 { 130 UpdateEdgeIntersection(); 131 132 spriteMeshView.BeginDrawEdges(); 133 134 for (var i = 0; i < spriteMeshData.edges.Length; ++i) 135 { 136 if (SkipDrawEdge(i)) 137 continue; 138 139 var edge = spriteMeshData.edges[i]; 140 var startPosition = spriteMeshData.vertices[edge.x]; 141 var endPosition = spriteMeshData.vertices[edge.y]; 142 143 if (selection.Contains(edge.x) && selection.Contains(edge.y)) 144 spriteMeshView.DrawEdgeSelected(startPosition, endPosition); 145 else 146 spriteMeshView.DrawEdge(startPosition, endPosition); 147 } 148 149 if (spriteMeshView.IsActionActive(MeshEditorAction.SelectEdge)) 150 { 151 var hoveredEdge = spriteMeshData.edges[spriteMeshView.hoveredEdge]; 152 var startPosition = spriteMeshData.vertices[hoveredEdge.x]; 153 var endPosition = spriteMeshData.vertices[hoveredEdge.y]; 154 155 spriteMeshView.DrawEdgeHovered(startPosition, endPosition); 156 } 157 158 spriteMeshView.EndDrawEdges(); 159 } 160 161 bool SkipDrawEdge(int edgeIndex) 162 { 163 if (GUI.enabled == false) 164 return false; 165 166 return edgeIndex == -1 || 167 spriteMeshView.hoveredEdge == edgeIndex && spriteMeshView.IsActionActive(MeshEditorAction.SelectEdge) || 168 spriteMeshView.hoveredEdge == edgeIndex && spriteMeshView.IsActionActive(MeshEditorAction.CreateVertex) || 169 spriteMeshView.closestEdge == edgeIndex && spriteMeshView.IsActionActive(MeshEditorAction.SplitEdge) || 170 edgeIndex == m_EdgeIntersectionResult.intersectEdgeIndex && spriteMeshView.IsActionActive(MeshEditorAction.CreateEdge); 171 } 172 173 void PreviewCreateVertex() 174 { 175 if (spriteMeshView.mode == SpriteMeshViewMode.CreateVertex && 176 spriteMeshView.IsActionActive(MeshEditorAction.CreateVertex)) 177 { 178 var clampedMousePos = ClampToFrame(spriteMeshView.mouseWorldPosition); 179 180 if (spriteMeshView.hoveredEdge != -1) 181 { 182 var edge = spriteMeshData.edges[spriteMeshView.hoveredEdge]; 183 184 spriteMeshView.BeginDrawEdges(); 185 186 spriteMeshView.DrawEdge(spriteMeshData.vertices[edge.x], clampedMousePos); 187 spriteMeshView.DrawEdge(spriteMeshData.vertices[edge.y], clampedMousePos); 188 189 spriteMeshView.EndDrawEdges(); 190 } 191 192 spriteMeshView.DrawVertex(clampedMousePos); 193 } 194 } 195 196 void PreviewCreateEdge() 197 { 198 if (!spriteMeshView.IsActionActive(MeshEditorAction.CreateEdge)) 199 return; 200 201 spriteMeshView.BeginDrawEdges(); 202 203 spriteMeshView.DrawEdge(spriteMeshData.vertices[m_EdgeIntersectionResult.startVertexIndex], m_EdgeIntersectionResult.endPosition); 204 205 if (m_EdgeIntersectionResult.intersectEdgeIndex != -1) 206 { 207 var intersectingEdge = spriteMeshData.edges[m_EdgeIntersectionResult.intersectEdgeIndex]; 208 spriteMeshView.DrawEdge(spriteMeshData.vertices[intersectingEdge.x], m_EdgeIntersectionResult.endPosition); 209 spriteMeshView.DrawEdge(spriteMeshData.vertices[intersectingEdge.y], m_EdgeIntersectionResult.endPosition); 210 } 211 212 spriteMeshView.EndDrawEdges(); 213 214 if (m_EdgeIntersectionResult.endVertexIndex == -1) 215 spriteMeshView.DrawVertex(m_EdgeIntersectionResult.endPosition); 216 } 217 218 void PreviewSplitEdge() 219 { 220 if (!spriteMeshView.IsActionActive(MeshEditorAction.SplitEdge)) 221 return; 222 223 var clampedMousePos = ClampToFrame(spriteMeshView.mouseWorldPosition); 224 225 var closestEdge = spriteMeshData.edges[spriteMeshView.closestEdge]; 226 227 spriteMeshView.BeginDrawEdges(); 228 229 spriteMeshView.DrawEdge(spriteMeshData.vertices[closestEdge.x], clampedMousePos); 230 spriteMeshView.DrawEdge(spriteMeshData.vertices[closestEdge.y], clampedMousePos); 231 232 spriteMeshView.EndDrawEdges(); 233 234 spriteMeshView.DrawVertex(clampedMousePos); 235 } 236 237 void DrawVertices() 238 { 239 for (var i = 0; i < spriteMeshData.vertexCount; i++) 240 { 241 var position = spriteMeshData.vertices[i]; 242 243 if (selection.Contains(i)) 244 spriteMeshView.DrawVertexSelected(position); 245 else if (i == spriteMeshView.hoveredVertex && spriteMeshView.IsActionHot(MeshEditorAction.None)) 246 spriteMeshView.DrawVertexHovered(position); 247 else 248 spriteMeshView.DrawVertex(position); 249 } 250 } 251 252 void HandleSelectVertex() 253 { 254 if (spriteMeshView.DoSelectVertex(out var additive)) 255 SelectVertex(spriteMeshView.hoveredVertex, additive); 256 } 257 258 void HandleSelectEdge() 259 { 260 if (spriteMeshView.DoSelectEdge(out var additive)) 261 SelectEdge(spriteMeshView.hoveredEdge, additive); 262 } 263 264 void HandleMoveVertexAndEdge() 265 { 266 if (selection.Count == 0) 267 return; 268 269 if (spriteMeshView.DoMoveVertex(out var finalDeltaPos) || spriteMeshView.DoMoveEdge(out finalDeltaPos)) 270 { 271 var selectionArray = selection.elements; 272 273 finalDeltaPos = MathUtility.MoveRectInsideFrame(CalculateRectFromSelection(), frame, finalDeltaPos); 274 var movedVertexSelection = GetMovedVertexSelection(in selectionArray, spriteMeshData.vertices, finalDeltaPos); 275 276 if (IsMovedEdgeIntersectingWithOtherEdge(in selectionArray, in movedVertexSelection, spriteMeshData.edges, spriteMeshData.vertices)) 277 return; 278 if (IsMovedVertexIntersectingWithOutline(in selectionArray, in movedVertexSelection, spriteMeshData.outlineEdges, spriteMeshData.vertices)) 279 return; 280 281 cacheUndo.BeginUndoOperation(TextContent.moveVertices); 282 MoveSelectedVertices(in movedVertexSelection); 283 } 284 } 285 286 void HandleCreateVertex() 287 { 288 if (spriteMeshView.DoCreateVertex()) 289 { 290 var position = ClampToFrame(spriteMeshView.mouseWorldPosition); 291 var edgeIndex = spriteMeshView.hoveredEdge; 292 if (spriteMeshView.hoveredEdge != -1) 293 CreateVertex(position, edgeIndex); 294 else if (m_SpriteMeshDataController.FindTriangle(position, out var indices, out var barycentricCoords)) 295 CreateVertex(position, indices, barycentricCoords); 296 } 297 } 298 299 void HandleSplitEdge() 300 { 301 if (spriteMeshView.DoSplitEdge()) 302 SplitEdge(ClampToFrame(spriteMeshView.mouseWorldPosition), spriteMeshView.closestEdge); 303 } 304 305 void HandleCreateEdge() 306 { 307 if (spriteMeshView.DoCreateEdge()) 308 { 309 var clampedMousePosition = ClampToFrame(spriteMeshView.mouseWorldPosition); 310 var edgeIntersectionResult = CalculateEdgeIntersection(selection.activeElement, spriteMeshView.hoveredVertex, spriteMeshView.hoveredEdge, clampedMousePosition); 311 312 if (edgeIntersectionResult.endVertexIndex != -1) 313 { 314 CreateEdge(selection.activeElement, edgeIntersectionResult.endVertexIndex); 315 } 316 else 317 { 318 if (edgeIntersectionResult.intersectEdgeIndex != -1) 319 { 320 CreateVertex(edgeIntersectionResult.endPosition, edgeIntersectionResult.intersectEdgeIndex); 321 CreateEdge(selection.activeElement, spriteMeshData.vertexCount - 1); 322 } 323 else if (m_SpriteMeshDataController.FindTriangle(edgeIntersectionResult.endPosition, out var indices, out var barycentricCoords)) 324 { 325 CreateVertex(edgeIntersectionResult.endPosition, indices, barycentricCoords); 326 CreateEdge(selection.activeElement, spriteMeshData.vertexCount - 1); 327 } 328 } 329 } 330 } 331 332 void HandleRemoveVertices() 333 { 334 if (spriteMeshView.DoRemove()) 335 RemoveSelectedVertices(); 336 } 337 338 void CreateVertex(Vector2 position, Vector3Int indices, Vector3 barycentricCoords) 339 { 340 var bw1 = spriteMeshData.vertexWeights[indices.x]; 341 var bw2 = spriteMeshData.vertexWeights[indices.y]; 342 var bw3 = spriteMeshData.vertexWeights[indices.z]; 343 344 var result = new EditableBoneWeight(); 345 346 foreach (var channel in bw1) 347 { 348 if (!channel.enabled) 349 continue; 350 351 var weight = channel.weight * barycentricCoords.x; 352 if (weight > 0f) 353 result.AddChannel(channel.boneIndex, weight, true); 354 } 355 356 foreach (var channel in bw2) 357 { 358 if (!channel.enabled) 359 continue; 360 361 var weight = channel.weight * barycentricCoords.y; 362 if (weight > 0f) 363 result.AddChannel(channel.boneIndex, weight, true); 364 } 365 366 foreach (var channel in bw3) 367 { 368 if (!channel.enabled) 369 continue; 370 371 var weight = channel.weight * barycentricCoords.z; 372 if (weight > 0f) 373 result.AddChannel(channel.boneIndex, weight, true); 374 } 375 376 result.UnifyChannelsWithSameBoneIndex(); 377 result.FilterChannels(0f); 378 result.Clamp(4, true); 379 380 var boneWeight = result.ToBoneWeight(true); 381 382 cacheUndo.BeginUndoOperation(TextContent.createVertex); 383 384 m_SpriteMeshDataController.CreateVertex(position, -1); 385 spriteMeshData.vertexWeights[spriteMeshData.vertexCount - 1].SetFromBoneWeight(boneWeight); 386 Triangulate(); 387 } 388 389 void CreateVertex(Vector2 position, int edgeIndex) 390 { 391 var edge = spriteMeshData.edges[edgeIndex]; 392 var pos1 = spriteMeshData.vertices[edge.x]; 393 var pos2 = spriteMeshData.vertices[edge.y]; 394 var dir1 = (position - pos1); 395 var dir2 = (pos2 - pos1); 396 var t = Vector2.Dot(dir1, dir2.normalized) / dir2.magnitude; 397 t = Mathf.Clamp01(t); 398 var bw1 = spriteMeshData.vertexWeights[edge.x].ToBoneWeight(true); 399 var bw2 = spriteMeshData.vertexWeights[edge.y].ToBoneWeight(true); 400 401 var boneWeight = EditableBoneWeightUtility.Lerp(bw1, bw2, t); 402 403 cacheUndo.BeginUndoOperation(TextContent.createVertex); 404 405 m_SpriteMeshDataController.CreateVertex(position, edgeIndex); 406 spriteMeshData.vertexWeights[spriteMeshData.vertexCount - 1].SetFromBoneWeight(boneWeight); 407 Triangulate(); 408 } 409 410 void SelectVertex(int index, bool additiveToggle) 411 { 412 if (index < 0) 413 throw new ArgumentException("Index out of range"); 414 415 var selected = selection.Contains(index); 416 if (selected) 417 { 418 if (additiveToggle) 419 { 420 cacheUndo.BeginUndoOperation(TextContent.selection); 421 selection.Select(index, false); 422 } 423 } 424 else 425 { 426 cacheUndo.BeginUndoOperation(TextContent.selection); 427 428 if (!additiveToggle) 429 ClearSelection(); 430 431 selection.Select(index, true); 432 } 433 434 cacheUndo.IncrementCurrentGroup(); 435 } 436 437 void SelectEdge(int index, bool additiveToggle) 438 { 439 Debug.Assert(index >= 0); 440 441 var edge = spriteMeshData.edges[index]; 442 443 cacheUndo.BeginUndoOperation(TextContent.selection); 444 445 var selected = selection.Contains(edge.x) && selection.Contains(edge.y); 446 if (selected) 447 { 448 if (additiveToggle) 449 { 450 selection.Select(edge.x, false); 451 selection.Select(edge.y, false); 452 } 453 } 454 else 455 { 456 if (!additiveToggle) 457 ClearSelection(); 458 459 selection.Select(edge.x, true); 460 selection.Select(edge.y, true); 461 } 462 463 cacheUndo.IncrementCurrentGroup(); 464 } 465 466 void ClearSelection() 467 { 468 cacheUndo.BeginUndoOperation(TextContent.selection); 469 selection.Clear(); 470 } 471 472 void MoveSelectedVertices(in Vector2[] movedVertices) 473 { 474 for (var i = 0; i < selection.Count; ++i) 475 { 476 var index = selection.elements[i]; 477 spriteMeshData.vertices[index] = movedVertices[i]; 478 } 479 480 Triangulate(); 481 } 482 483 void CreateEdge(int fromVertexIndex, int toVertexIndex) 484 { 485 cacheUndo.BeginUndoOperation(TextContent.createEdge); 486 487 m_SpriteMeshDataController.CreateEdge(fromVertexIndex, toVertexIndex); 488 Triangulate(); 489 ClearSelection(); 490 selection.Select(toVertexIndex, true); 491 492 cacheUndo.IncrementCurrentGroup(); 493 } 494 495 void SplitEdge(Vector2 position, int edgeIndex) 496 { 497 cacheUndo.BeginUndoOperation(TextContent.splitEdge); 498 499 CreateVertex(position, edgeIndex); 500 501 cacheUndo.IncrementCurrentGroup(); 502 } 503 504 bool IsEdgeSelected() 505 { 506 if (selection.Count != 2) 507 return false; 508 509 var indices = selection.elements; 510 511 var index1 = indices[0]; 512 var index2 = indices[1]; 513 514 var edge = new int2(index1, index2); 515 return spriteMeshData.edges.ContainsAny(edge); 516 } 517 518 void RemoveSelectedVertices() 519 { 520 cacheUndo.BeginUndoOperation(IsEdgeSelected() ? TextContent.removeEdge : TextContent.removeVertices); 521 522 var verticesToRemove = selection.elements; 523 524 var noOfVertsToDelete = verticesToRemove.Length; 525 var noOfVertsInMesh = m_SpriteMeshDataController.spriteMeshData.vertexCount; 526 var shouldClearMesh = (noOfVertsInMesh - noOfVertsToDelete) < 3; 527 528 if (shouldClearMesh) 529 { 530 m_SpriteMeshDataController.spriteMeshData.Clear(); 531 m_SpriteMeshDataController.CreateQuad(); 532 } 533 else 534 m_SpriteMeshDataController.RemoveVertex(verticesToRemove); 535 536 Triangulate(); 537 538 selection.Clear(); 539 } 540 541 void Triangulate() 542 { 543 m_SpriteMeshDataController.Triangulate(triangulator); 544 m_SpriteMeshDataController.SortTrianglesByDepth(); 545 } 546 547 Vector2 ClampToFrame(Vector2 position) 548 { 549 return MathUtility.ClampPositionToRect(position, frame); 550 } 551 552 Rect CalculateRectFromSelection() 553 { 554 var rect = new Rect(); 555 556 var min = new Vector2(float.MaxValue, float.MaxValue); 557 var max = new Vector2(float.MinValue, float.MinValue); 558 559 var indices = selection.elements; 560 561 foreach (var index in indices) 562 { 563 var v = spriteMeshData.vertices[index]; 564 565 min.x = Mathf.Min(min.x, v.x); 566 min.y = Mathf.Min(min.y, v.y); 567 568 max.x = Mathf.Max(max.x, v.x); 569 max.y = Mathf.Max(max.y, v.y); 570 } 571 572 rect.min = min; 573 rect.max = max; 574 575 return rect; 576 } 577 578 void UpdateEdgeIntersection() 579 { 580 if (selection.Count == 1) 581 m_EdgeIntersectionResult = CalculateEdgeIntersection(selection.activeElement, spriteMeshView.hoveredVertex, spriteMeshView.hoveredEdge, ClampToFrame(spriteMeshView.mouseWorldPosition)); 582 } 583 584 EdgeIntersectionResult CalculateEdgeIntersection(int vertexIndex, int hoveredVertexIndex, int hoveredEdgeIndex, Vector2 targetPosition) 585 { 586 Debug.Assert(vertexIndex >= 0); 587 588 var edgeIntersection = new EdgeIntersectionResult 589 { 590 startVertexIndex = vertexIndex, 591 endVertexIndex = hoveredVertexIndex, 592 endPosition = targetPosition, 593 intersectEdgeIndex = -1 594 }; 595 596 var startPoint = spriteMeshData.vertices[edgeIntersection.startVertexIndex]; 597 598 var intersectsEdge = false; 599 var lastIntersectingEdgeIndex = -1; 600 601 do 602 { 603 lastIntersectingEdgeIndex = edgeIntersection.intersectEdgeIndex; 604 605 if (intersectsEdge) 606 { 607 var dir = edgeIntersection.endPosition - startPoint; 608 edgeIntersection.endPosition += dir.normalized * 10f; 609 } 610 611 intersectsEdge = SegmentIntersectsEdge(startPoint, edgeIntersection.endPosition, vertexIndex, ref edgeIntersection.endPosition, out edgeIntersection.intersectEdgeIndex); 612 613 //if we are hovering a vertex and intersect an edge indexing it we forget about the intersection 614 var edges = spriteMeshData.edges; 615 var edge = intersectsEdge ? edges[edgeIntersection.intersectEdgeIndex] : default; 616 if (intersectsEdge && (edge.x == edgeIntersection.endVertexIndex || edge.y == edgeIntersection.endVertexIndex)) 617 { 618 edgeIntersection.intersectEdgeIndex = -1; 619 intersectsEdge = false; 620 edgeIntersection.endPosition = spriteMeshData.vertices[edgeIntersection.endVertexIndex]; 621 } 622 623 if (intersectsEdge) 624 { 625 edgeIntersection.endVertexIndex = -1; 626 627 var intersectingEdge = spriteMeshData.edges[edgeIntersection.intersectEdgeIndex]; 628 var newPointScreen = spriteMeshView.WorldToScreen(edgeIntersection.endPosition); 629 var edgeV1 = spriteMeshView.WorldToScreen(spriteMeshData.vertices[intersectingEdge.x]); 630 var edgeV2 = spriteMeshView.WorldToScreen(spriteMeshData.vertices[intersectingEdge.y]); 631 632 if ((newPointScreen - edgeV1).magnitude <= k_SnapDistance) 633 edgeIntersection.endVertexIndex = intersectingEdge.x; 634 else if ((newPointScreen - edgeV2).magnitude <= k_SnapDistance) 635 edgeIntersection.endVertexIndex = intersectingEdge.y; 636 637 if (edgeIntersection.endVertexIndex != -1) 638 { 639 edgeIntersection.intersectEdgeIndex = -1; 640 intersectsEdge = false; 641 edgeIntersection.endPosition = spriteMeshData.vertices[edgeIntersection.endVertexIndex]; 642 } 643 } 644 } while (intersectsEdge && lastIntersectingEdgeIndex != edgeIntersection.intersectEdgeIndex); 645 646 edgeIntersection.intersectEdgeIndex = intersectsEdge ? edgeIntersection.intersectEdgeIndex : hoveredEdgeIndex; 647 648 if (edgeIntersection.endVertexIndex != -1 && !intersectsEdge) 649 edgeIntersection.endPosition = spriteMeshData.vertices[edgeIntersection.endVertexIndex]; 650 651 return edgeIntersection; 652 } 653 654 bool SegmentIntersectsEdge(Vector2 p1, Vector2 p2, int ignoreIndex, ref Vector2 point, out int intersectingEdgeIndex) 655 { 656 intersectingEdgeIndex = -1; 657 658 var sqrDistance = float.MaxValue; 659 660 for (var i = 0; i < spriteMeshData.edges.Length; i++) 661 { 662 var edge = spriteMeshData.edges[i]; 663 var v1 = spriteMeshData.vertices[edge.x]; 664 var v2 = spriteMeshData.vertices[edge.y]; 665 var pointTmp = Vector2.zero; 666 667 if (edge.x != ignoreIndex && edge.y != ignoreIndex && 668 MathUtility.SegmentIntersection(p1, p2, v1, v2, ref pointTmp)) 669 { 670 var sqrMagnitude = (pointTmp - p1).sqrMagnitude; 671 if (sqrMagnitude < sqrDistance) 672 { 673 sqrDistance = sqrMagnitude; 674 intersectingEdgeIndex = i; 675 point = pointTmp; 676 } 677 } 678 } 679 680 return intersectingEdgeIndex != -1; 681 } 682 683 684 static Vector2[] GetMovedVertexSelection(in int[] selection, in Vector2[] vertices, Vector2 deltaPosition) 685 { 686 var movedVertices = new Vector2[selection.Length]; 687 for (var i = 0; i < selection.Length; i++) 688 { 689 var index = selection[i]; 690 movedVertices[i] = vertices[index] + deltaPosition; 691 } 692 693 return movedVertices; 694 } 695 696 static bool IsMovedEdgeIntersectingWithOtherEdge(in int[] selection, in Vector2[] movedVertices, in int2[] meshEdges, in Vector2[] meshVertices) 697 { 698 var edgeCount = meshEdges.Length; 699 var edgeIntersectionPoint = Vector2.zero; 700 701 for (var i = 0; i < edgeCount; i++) 702 { 703 var selectionIndex = FindSelectionIndexFromEdge(selection, meshEdges[i]); 704 if (selectionIndex.x == -1 && selectionIndex.y == -1) 705 continue; 706 707 var edgeStart = selectionIndex.x != -1 ? movedVertices[selectionIndex.x] : meshVertices[meshEdges[i].x]; 708 var edgeEnd = selectionIndex.y != -1 ? movedVertices[selectionIndex.y] : meshVertices[meshEdges[i].y]; 709 710 for (var o = 0; o < edgeCount; o++) 711 { 712 if (o == i) 713 continue; 714 715 if (meshEdges[i].x == meshEdges[o].x || meshEdges[i].y == meshEdges[o].x || 716 meshEdges[i].x == meshEdges[o].y || meshEdges[i].y == meshEdges[o].y) 717 continue; 718 719 var otherSelectionIndex = FindSelectionIndexFromEdge(in selection, meshEdges[o]); 720 var otherEdgeStart = otherSelectionIndex.x != -1 ? movedVertices[otherSelectionIndex.x] : meshVertices[meshEdges[o].x]; 721 var otherEdgeEnd = otherSelectionIndex.y != -1 ? movedVertices[otherSelectionIndex.y] : meshVertices[meshEdges[o].y]; 722 723 if (MathUtility.SegmentIntersection(edgeStart, edgeEnd, otherEdgeStart, otherEdgeEnd, ref edgeIntersectionPoint)) 724 return true; 725 } 726 } 727 728 return false; 729 } 730 731 static int2 FindSelectionIndexFromEdge(in int[] selection, int2 edge) 732 { 733 var selectionIndex = new int2(-1, -1); 734 for (var m = 0; m < selection.Length; ++m) 735 { 736 if (selection[m] == edge.x) 737 { 738 selectionIndex.x = m; 739 break; 740 } 741 742 if (selection[m] == edge.y) 743 { 744 selectionIndex.y = m; 745 break; 746 } 747 } 748 749 return selectionIndex; 750 } 751 752 static bool IsMovedVertexIntersectingWithOutline(in int[] selection, in Vector2[] movedVertices, in int2[] outlineEdges, in Vector2[] meshVertices) 753 { 754 var edgeIntersectionPoint = Vector2.zero; 755 756 for (var i = 0; i < selection.Length; ++i) 757 { 758 var edgeStart = meshVertices[selection[i]]; 759 var edgeEnd = movedVertices[i]; 760 761 for (var m = 0; m < outlineEdges.Length; ++m) 762 { 763 if (selection[i] == outlineEdges[m].x || selection[i] == outlineEdges[m].y) 764 continue; 765 766 var otherSelectionIndex = FindSelectionIndexFromEdge(in selection, outlineEdges[m]); 767 var otherEdgeStart = otherSelectionIndex.x != -1 ? movedVertices[otherSelectionIndex.x] : meshVertices[outlineEdges[m].x]; 768 var otherEdgeEnd = otherSelectionIndex.y != -1 ? movedVertices[otherSelectionIndex.y] : meshVertices[outlineEdges[m].y]; 769 770 if (MathUtility.SegmentIntersection(edgeStart, edgeEnd, otherEdgeStart, otherEdgeEnd, ref edgeIntersectionPoint)) 771 return true; 772 } 773 } 774 775 return false; 776 } 777 } 778}