using System; using KitsuneCafe.ItemSystem; using KitsuneCafe.SOAP; using KitsuneCafe.Sys; using R3; using UnityEngine; using Wacs.Core.Instructions; namespace KitsuneCafe.UI { public class ItemPreview : MonoBehaviour { [SerializeField] private ItemValue selectedItem; [SerializeField] private new Transform camera; [Header("Rotation")] [SerializeField] private Vector2Value rotationDelta; [SerializeField] private float sensitivity = 20; [SerializeField] private float angleSnap = 10; [Header("Zoom")] [SerializeField] private FloatValue zoom; [SerializeField] private float zoomSensitivity = 0.5f; private Vector3 initialPosition; [SerializeField] private Layer previewLayer; private GameObject instance; private void Start() { if (selectedItem.Value != null) { ChangeItemPreview(selectedItem.Value); } var d = Disposable.CreateBuilder(); selectedItem.AsObservable() .Subscribe(ChangeItemPreview) .AddTo(ref d); rotationDelta.AsObservable() .Where(_ => instance != null) .Subscribe(RotatePreview) .AddTo(ref d); zoom.AsObservable() .Where(_ => instance != null) .Subscribe(ZoomPreview) .AddTo(ref d); d.RegisterTo(destroyCancellationToken); } private void ZoomPreview(float amount) { if (instance == null) { return; } var position = initialPosition; position.z += amount * zoomSensitivity; instance.transform.position = position; } private void ChangeItemPreview(Item item) { if (instance != null) { Destroy(instance); instance = null; } if (item != null) { instance = item.CreatePreview(); instance.layer = previewLayer; instance.transform.SetParent(transform); initialPosition = instance.transform.position; ResetPreviewValues(); } } private void ResetPreviewValues() { zoom.Value = 0; rotationDelta.Value = Vector2.zero; } public void RotatePreview(Vector2 delta) { if (instance == null || camera == null) { return; } var yawAngle = -delta.x * sensitivity * Time.deltaTime; var yawRotation = Quaternion.AngleAxis(yawAngle, camera.up); var pitchAngle = -delta.y * sensitivity * Time.deltaTime; var pitchRotation = Quaternion.AngleAxis(pitchAngle, camera.right); var combinedRotation = pitchRotation * yawRotation; instance.transform.rotation = combinedRotation * instance.transform.rotation; ApplyAngleSnapping(); } public void ApplyAngleSnapping() { if (instance == null) return; Vector3 euler = instance.transform.rotation.eulerAngles; Quaternion rotation = Quaternion.Euler( Mathf.Round(euler.x / angleSnap) * angleSnap, Mathf.Round(euler.y / angleSnap) * angleSnap, Mathf.Round(euler.z / angleSnap) * angleSnap ); instance.transform.rotation = rotation; } } }