Files
2026-07-21 08:56:10 +03:00

58 lines
2.8 KiB
C#

using UnityEngine;
/// <summary>
/// regulare snap performed in free move
/// </summary>
public class DefaultSnapBehavior : ISnapBehavior
{
public bool TrySnap(BlockEditContext ctx)
{
if (ctx.TargetSocket == null) return false;
if (ctx.MySocket != null && !ctx.TargetSocket.CanAccept(ctx.MySocket)) return false;
if (ctx.MySocket != null)
{
// 1. Primary Alignment: Align the exact socket normals
Vector3 myNormal = ctx.MySocket.GetNormal().normalized;
Vector3 targetNormal = -ctx.TargetSocket.GetNormal().normalized;
Quaternion primaryRot = Quaternion.FromToRotation(myNormal, targetNormal);
ctx.GhostTransform.rotation = primaryRot * ctx.GhostTransform.rotation;
// 2. Secondary Alignment: Align the 'Up' (or Forward) vectors to prevent random twisting/rolling
Vector3 mySecondary = Mathf.Abs(Vector3.Dot(ctx.MySocket.transform.up, targetNormal)) < 0.9f
? ctx.MySocket.transform.up
: ctx.MySocket.transform.forward;
Vector3 targetSecondary = Mathf.Abs(Vector3.Dot(ctx.TargetSocket.transform.up, -targetNormal)) < 0.9f
? ctx.TargetSocket.transform.up
: ctx.TargetSocket.transform.forward;
// Project secondary vectors onto the flat plane between the sockets
Vector3 projectedMySecondary = Vector3.ProjectOnPlane(mySecondary, targetNormal).normalized;
Vector3 projectedTargetSecondary = Vector3.ProjectOnPlane(targetSecondary, targetNormal).normalized;
if (projectedMySecondary != Vector3.zero && projectedTargetSecondary != Vector3.zero)
{
// Find the twist angle needed to align the secondary axes
float angle = Vector3.SignedAngle(projectedMySecondary, projectedTargetSecondary, targetNormal);
// Snap to the nearest 45 degrees to allow manual 'R' rotations to persist!
float correction = angle - Mathf.Round(angle / 45f) * 45f;
// Rotate the ghost around its own pivot (since we haven't translated yet)
ctx.GhostTransform.rotation = Quaternion.AngleAxis(correction, targetNormal) * ctx.GhostTransform.rotation;
}
// 3. Translate the ghost so the sockets physically touch
ctx.GhostTransform.position +=
ctx.TargetSocket.transform.position - ctx.MySocket.transform.position;
}
else
{
Transform pivot = ctx.AttachPoint != null ? ctx.AttachPoint : ctx.GhostTransform;
Vector3 pivotOffset = pivot.position - ctx.GhostTransform.position;
ctx.GhostTransform.position = ctx.TargetSocket.transform.position - pivotOffset;
}
return true;
}
}