using System.Collections.Generic; using UnityEditor; using UnityEngine; [SelectionBase] public class SnapPoint : MonoBehaviour { public SnapPoint SnapTarget; public SnappableRoom _snappableRoom => GetComponentInParent<SnappableRoom>(); [ContextMenu("SnapToMyTarget")] public void SnapToMySnapTarget() => SnapTo(SnapTarget); public void SnapTo(SnapPoint other) { Undo.RecordObject(_snappableRoom.transform, "SnapTo"); var offset = _snappableRoom.transform.position - transform.position; var newPosition = other.transform.position + offset; _snappableRoom.transform.position = newPosition; OpenChildHallParts(this); OpenChildHallParts(other); } void OpenChildHallParts(SnapPoint other) { var hallPartToOpen = other.GetComponentInChildren<HallPart>(); if (hallPartToOpen != null) hallPartToOpen.SetMode(OpeningMode.Open); } public void AlignTo(SnapPoint other) { var rotationOffset = transform.rotation.eulerAngles.y - _snappableRoom.transform.rotation.eulerAngles.y; Undo.RecordObject(_snappableRoom.transform, "AlignTo"); _snappableRoom.transform.rotation = other.transform.rotation; _snappableRoom.transform.Rotate(0, 180, 0); _snappableRoom.transform.Rotate(0, -rotationOffset, 0); } [ContextMenu("Align and Snap To Me &m")] public void SnapAndAlignOtherToMe() { if (SnapTarget != null) { SnapTarget.AlignTo(this); SnapTarget.SnapTo(this); } } [ContextMenu("Connect 2 SnapPoints")] public void Connect2() { if (Selection.objects.Length != 2) { Debug.LogError("Connect 2 requires exactly 2 snap points be selected"); return; } var snapO1 = Selection.objects[0]; var snap1 = (snapO1 as GameObject)?.GetComponent<SnapPoint>(); var snapO2 = Selection.objects[1]; var snap2 = (snapO2 as GameObject)?.GetComponent<SnapPoint>(); if (snap1 && snap2) { snap2.SnapTarget = snap1; snap1.SnapTarget = snap2; } } [ContextMenu("Snap And Align to Other")] public void SnapAndAlign() { if (SnapTarget != null) { AlignTo(SnapTarget); SnapTo(SnapTarget); } } void OnDrawGizmos() { Gizmos.color = UnityEngine.Color.green; if (SnapTarget != null) Gizmos.DrawLine(transform.position, SnapTarget.transform.position); } void OnValidate() { if (SnapTarget == null) SnapTarget = null; bool showVisuals = true; foreach (var child in transform.GetComponentsInChildren<Transform>(true)) if (child.name == "Snap Point Visualizer") child.gameObject.SetActive(showVisuals); } public SnapPoint FindNearestOther(IEnumerable<SnapPoint> others, float maxDistance = 10f) { SnapPoint closest = null; var closestDistance = float.MaxValue; foreach (var other in others) { if (other == this || other._snappableRoom == _snappableRoom) continue; if (other.SnapTarget != null) continue; var dist = Vector3.Distance(transform.position, other.transform.position); if (dist > maxDistance) continue; if (dist < closestDistance) { closestDistance = dist; closest = other; } } return closest; } }