ZeroVR/ZeroPacientVR/Assets/Octave3D World Builder/Scripts/Objects/Object Snapping/ObjectVertexSnapSession.cs

259 lines
11 KiB
C#

#if UNITY_EDITOR
using UnityEngine;
using System.Collections.Generic;
namespace O3DWB
{
public class ObjectVertexSnapSession
{
#region Private Variables
private GameObject _sourceObject;
private List<GameObject> _sourceObjects;
private List<GameObject> _sourceParents;
private GameObject _destinationObject;
private XZGridCell _destinationGridCell;
private Vector3 _sourceVertex;
private Vector3 _snapPosition;
private ObjectVertexSnapSessionState _state;
private bool _isActive;
private ObjectMask _objectMask = new ObjectMask();
#endregion
#region Public Properties
public bool IsActive { get { return _isActive; } }
public GameObject SourceGameObject { get { return _sourceObject; } }
public bool HasMultipleSourceObjects { get { return _sourceObjects != null && _sourceObjects.Count != 0; } }
public GameObject DestinationGameObject { get { return _destinationObject; } }
public XZGridCell DestinationGridCell { get { return _destinationGridCell != null ? new XZGridCell(_destinationGridCell) : null; } }
public Vector3 SourceVertex { get { return _sourceVertex; } }
public Vector3 SnapPosition { get { return _snapPosition; } }
public ObjectVertexSnapSessionState State { get { return _state; } }
#endregion
#region Public Methods
public void Begin()
{
if (_isActive) return;
_isActive = true;
ResetData();
_state = ObjectVertexSnapSessionState.SelectSourceVertex;
}
public void Begin(List<GameObject> sourceObjects)
{
if (_isActive) return;
if (sourceObjects.Count == 0) return;
_isActive = true;
ResetData();
_sourceObjects = new List<GameObject>(sourceObjects);
_sourceParents = Octave3DWorldBuilder.ActiveInstance.GetRoots(_sourceObjects);
foreach (var parent in _sourceParents)
_objectMask.ObjectCollectionMask.Mask(parent.GetAllChildrenIncludingSelf());
_state = ObjectVertexSnapSessionState.SelectSourceVertex;
}
public void End()
{
_isActive = false;
ResetData();
}
public void UpdateForMouseMovement()
{
if (!_isActive) return;
if (MouseButtonStates.Instance.IsMouseButtonDown(MouseButton.Left)) _state = ObjectVertexSnapSessionState.SnapToDestination;
else _state = ObjectVertexSnapSessionState.SelectSourceVertex;
if (_state == ObjectVertexSnapSessionState.SelectSourceVertex)
{
if (_sourceObjects == null || _sourceObjects.Count == 0)
{
_objectMask.ObjectCollectionMask.UnmaskAll();
MouseCursorRayHit cursorRayHit = GetCursorRayHit();
if (cursorRayHit.WasAnObjectHit)
{
GameObjectRayHit objectRayHit = cursorRayHit.ClosestObjectRayHit;
MeshRayHit meshRayHit = objectRayHit.ObjectMeshHit;
if (meshRayHit != null)
{
Octave3DMesh octaveMesh = meshRayHit.HitMesh;
Triangle3D sourceTriangle = octaveMesh.GetTriangle(meshRayHit.HitTriangleIndex);
sourceTriangle.TransformPoints(objectRayHit.HitObject.transform.localToWorldMatrix);
_sourceVertex = sourceTriangle.GetPointClosestToPoint(meshRayHit.HitPoint);
_sourceObject = objectRayHit.HitObject;
_objectMask.ObjectCollectionMask.Mask(_sourceObject.transform.root.gameObject.GetAllChildrenIncludingSelf());
}
else
{
SpriteRenderer spriteRenderer = objectRayHit.HitObject.GetComponent<SpriteRenderer>();
if (spriteRenderer != null)
{
_sourceObject = objectRayHit.HitObject;
_sourceVertex = Vector3Extensions.GetClosestPointToPoint(objectRayHit.ObjectBoxHit.HitBox.GetCenterAndCornerPoints(), objectRayHit.HitPoint);
_objectMask.ObjectCollectionMask.Mask(_sourceObject.transform.root.gameObject.GetAllChildrenIncludingSelf());
}
}
}
}
else
{
MouseCursorRayHit cursorRayHit = GetCursorRayHit();
if (cursorRayHit.WasAnObjectHit)
{
GameObjectRayHit objectRayHit = cursorRayHit.ClosestObjectRayHit;
MeshRayHit meshRayHit = objectRayHit.ObjectMeshHit;
if (meshRayHit != null)
{
Octave3DMesh octaveMesh = meshRayHit.HitMesh;
Triangle3D sourceTriangle = octaveMesh.GetTriangle(meshRayHit.HitTriangleIndex);
sourceTriangle.TransformPoints(objectRayHit.HitObject.transform.localToWorldMatrix);
_sourceVertex = sourceTriangle.GetPointClosestToPoint(meshRayHit.HitPoint);
}
else
{
SpriteRenderer spriteRenderer = objectRayHit.HitObject.GetComponent<SpriteRenderer>();
if (spriteRenderer != null)
{
_sourceVertex = Vector3Extensions.GetClosestPointToPoint(objectRayHit.ObjectBoxHit.HitBox.GetCenterAndCornerPoints(), objectRayHit.HitPoint);
}
}
}
foreach (var parent in _sourceParents)
_objectMask.ObjectCollectionMask.Mask(parent.GetAllChildrenIncludingSelf());
}
}
else
{
MouseCursorRayHit cursorRayHit = GetCursorRayHit();
if (cursorRayHit.WasAnythingHit)
{
bool useGridCellHit = false;
if (!cursorRayHit.WasAnObjectHit) useGridCellHit = true;
else
if (cursorRayHit.WasAnObjectHit && cursorRayHit.WasACellHit)
{
float gridCellHitEnter = cursorRayHit.GridCellRayHit.HitEnter;
float objectHitEnter = cursorRayHit.ClosestObjectRayHit.HitEnter;
if (gridCellHitEnter < Mathf.Max(0.0f, (objectHitEnter - 1e-3f))) useGridCellHit = true;
}
if (useGridCellHit)
{
XZGridCell hitCell = cursorRayHit.GridCellRayHit.HitCell;
XZOrientedQuad3D cellQuad = hitCell.Quad;
_destinationObject = null;
_destinationGridCell = hitCell;
_snapPosition = cellQuad.GetPointClosestToPoint(cursorRayHit.GridCellRayHit.HitPoint, true);
SnapToDestination();
}
else
{
GameObjectRayHit objectRayHit = cursorRayHit.ClosestObjectRayHit;
MeshRayHit meshRayHit = objectRayHit.ObjectMeshHit;
if (meshRayHit != null)
{
_destinationObject = objectRayHit.HitObject;
Triangle3D destinationTriangle = meshRayHit.HitMesh.GetTriangle(meshRayHit.HitTriangleIndex);
destinationTriangle.TransformPoints(_destinationObject.transform.localToWorldMatrix);
_destinationGridCell = null;
_snapPosition = destinationTriangle.GetPointClosestToPoint(meshRayHit.HitPoint);
SnapToDestination();
}
else
{
SpriteRenderer spriteRenderer = objectRayHit.HitObject.GetComponent<SpriteRenderer>();
if (spriteRenderer != null)
{
_destinationGridCell = null;
_destinationObject = objectRayHit.HitObject;
_snapPosition = Vector3Extensions.GetClosestPointToPoint(objectRayHit.ObjectBoxHit.HitBox.GetCenterAndCornerPoints(), objectRayHit.HitPoint);
SnapToDestination();
}
}
}
}
}
}
#endregion
#region Private Methods
private void ResetData()
{
_sourceObject = null;
if (_sourceObjects != null) _sourceObjects.Clear();
_sourceObjects = null;
_destinationObject = null;
_destinationGridCell = null;
_objectMask.ObjectCollectionMask.UnmaskAll();
}
private MouseCursorRayHit GetCursorRayHit()
{
if (_sourceObjects == null || _state == ObjectVertexSnapSessionState.SnapToDestination)
{
MouseCursor.Instance.PushObjectMask(_objectMask);
MouseCursor.Instance.PushObjectPickMaskFlags(MouseCursorObjectPickFlags.ObjectBox | MouseCursorObjectPickFlags.ObjectTerrain);
MouseCursorRayHit cursorRayHit = MouseCursor.Instance.GetRayHit();
MouseCursor.Instance.PopObjectPickMaskFlags();
MouseCursor.Instance.PopObjectMask();
return cursorRayHit;
}
else
{
return MouseCursor.Instance.GetRayHitForMeshAndSpriteObjects(_sourceObjects);
}
}
private void SnapToDestination()
{
Vector3 snapVector = _snapPosition - _sourceVertex;
if (_sourceObjects == null)
{
GameObject root = Octave3DWorldBuilder.ActiveInstance.GetRoot(_sourceObject);
if (root != null)
{
Transform parentTransform = root.transform;
UndoEx.RecordForToolAction(parentTransform);
parentTransform.position += snapVector;
_sourceVertex += snapVector;
}
}
else
{
foreach (var parent in _sourceParents)
{
Transform parentTransform = parent.transform;
UndoEx.RecordForToolAction(parentTransform);
parentTransform.position += snapVector;
}
_sourceVertex += snapVector;
}
}
#endregion
}
}
#endif