using System.Linq; using Sirenix.OdinInspector; using Sirenix.Utilities; using UnityEngine; using UnityEngine.Rendering; using VOID.Generic.Objects.Item; using VOID.Generic.Trajectory; namespace VOID.Generic.Player { [DefaultExecutionOrder(-1)] public class DraggingVisualizer : MonoBehaviour { [ShowInInspector] private Transform _transformStart; [ShowInInspector] private Transform _transformEnd; private Vector3 _positionStart; private Vector3 _positionEnd; private Vector3 _lastPositionStart; private Vector3 _lastPositionEnd; private LineRenderer _lineRenderer; private ParabolicTrajectory _trajectory = new(); public static DraggingVisualizer Create(Transform transformStart, Transform transformEnd, ItemObject item) { // Prepare for scene dragging var go = Instantiate(item.gameObject); go.name = "Dragging Visualizer Dummy - " + go.name; go.transform.localPosition = Vector3.zero; go.transform.rotation = Quaternion.Euler(0, go.transform.rotation.eulerAngles.y, 0); // Remove everything except rendering components go.GetComponentsInChildren() .Where(component => component is not Transform and not MeshFilter and not MeshRenderer) .ForEach(component => Destroy(component)); // Make sure that our dummy don't copy highlight/outlines go.GetComponentsInChildren() .FilterCast() .ForEach(meshRenderer => meshRenderer.sharedMaterials = meshRenderer.sharedMaterials .Where(material => !HighlightManager.current.shaders.Contains(material.shader)) .ToArray()); var draggingVisualizer = go.AddComponent(); draggingVisualizer._transformStart = transformStart; draggingVisualizer._transformEnd = transformEnd; // Nice trajectory how item move draggingVisualizer._lineRenderer = go.AddComponent(); draggingVisualizer._lineRenderer.startWidth = 0.1f; draggingVisualizer._lineRenderer.endWidth = 0.1f; draggingVisualizer._lineRenderer.shadowCastingMode = ShadowCastingMode.Off; draggingVisualizer._trajectory.height = 1f; return draggingVisualizer; } private void FixedUpdate() { if (!_transformStart || !_transformEnd) return; _positionStart = _transformStart.position; _positionEnd = _transformEnd.position; if (_positionStart == _lastPositionStart && _positionEnd == _lastPositionEnd) return; _lastPositionStart = _positionStart; _lastPositionEnd = _positionEnd; transform.position = _positionEnd; if (gameObject.activeSelf) UpdateTrajectory(); } private void UpdateTrajectory() { _trajectory.Init(_positionStart, _positionEnd); var pointsNeeded = Mathf.Max(1, Mathf.FloorToInt(_trajectory.trajectoryDistance)) * 10; var points = _trajectory.GetPositions(pointsNeeded); _lineRenderer.positionCount = points.Length; _lineRenderer.SetPositions(points); } public void Show() { gameObject.SetActive(true); } public void Hide() { gameObject.SetActive(false); } } }