feat: SongCreator 씬 완성 — Beat Sage URL 지원, info.dat 메타데이터 자동 추출
- BeatSageUploader: audio_url 지원(UploadFromUrl), PollAndDownload 공통화, ZIP 500 오류 3회 재시도 - BeatSageConverter: info.dat 파싱(SongMetadata), BPM 자동 감지 → 노트 타이밍 변환에 적용 - SongCreatorManager: title/BPM 필수 입력 제거, 난이도 4개 자동 선택, GenerateFlowFromUrl 버그 수정 - NasPublisher: audioPath null 허용(URL 흐름에서 로컬 파일 없는 경우 스킵) - .gitignore/.gitattributes 초기 설정 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,370 @@
|
||||
using UnityEngine;
|
||||
using System.Collections.Generic;
|
||||
using VRSDK.Events;
|
||||
|
||||
namespace VRSDK
|
||||
{
|
||||
public enum InteractableType
|
||||
{
|
||||
Distance,
|
||||
Collider
|
||||
}
|
||||
|
||||
//basic class for all interactable components
|
||||
public class VR_Interactable : MonoBehaviour
|
||||
{
|
||||
[SerializeField] protected InteractableType interactableType = InteractableType.Distance;
|
||||
[SerializeField] protected VR_InputButton interactButton = VR_InputButton.Grip;
|
||||
[SerializeField] protected float interactDistance = 1.0f;
|
||||
[SerializeField] protected Collider grabCollider = null;
|
||||
[SerializeField] protected VR_HandInteractSettings rightHandSettings = new VR_HandInteractSettings();
|
||||
[SerializeField] protected VR_HandInteractSettings leftHandSettings = new VR_HandInteractSettings();
|
||||
[SerializeField] protected VR_HandInteractSettings handSettings = new VR_HandInteractSettings();
|
||||
[SerializeField] protected VR_HandAnimationSettings rightHandAnimationSettings = new VR_HandAnimationSettings();
|
||||
[SerializeField] protected VR_HandAnimationSettings leftHandAnimationSettings = new VR_HandAnimationSettings();
|
||||
[SerializeField] protected VR_HandAnimationSettings handAnimationSettings = new VR_HandAnimationSettings();
|
||||
[SerializeField] protected OnInteractEvent onInteractEvent = null;
|
||||
[SerializeField] protected bool shareHandInteractionSettings = false;
|
||||
[SerializeField] protected bool shareHandAnimationSettings = false;
|
||||
[SerializeField] protected bool useDistanceGrab = false;
|
||||
|
||||
|
||||
public bool UseDistanceGrab { get { return useDistanceGrab; } }
|
||||
public float DistanceToLeftHand { get; private set; }
|
||||
public float DistanceToRightHand { get; private set; }
|
||||
public float InteractDistance { get { return interactDistance; } }
|
||||
public bool CanInteract
|
||||
{
|
||||
get
|
||||
{
|
||||
return canInteract;
|
||||
}
|
||||
protected set
|
||||
{
|
||||
canInteract = value;
|
||||
|
||||
if (!canInteract)
|
||||
{
|
||||
VR_Highlight h = GetComponent<VR_Highlight>();
|
||||
|
||||
if (h != null)
|
||||
h.UnHighlight(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
public OnInteractEvent OnInteractEvent { get { return onInteractEvent; } }
|
||||
public InteractableType InteractableType => interactableType;
|
||||
|
||||
protected bool m_buttonWasPressedLeft = false;
|
||||
protected bool m_buttonWasPressedRight = false;
|
||||
|
||||
private bool canInteract = true;
|
||||
private VR_ControllerInfo rightControllerInfo = null;
|
||||
private VR_ControllerInfo leftControllerInfo = null;
|
||||
private List<VR_Controller> activeDistanceGrabControllerList = new List<VR_Controller>();
|
||||
private Transform cacheTransform = null;
|
||||
|
||||
protected Transform thisTransform
|
||||
{
|
||||
get
|
||||
{
|
||||
if (cacheTransform == null)
|
||||
{
|
||||
cacheTransform = transform;
|
||||
}
|
||||
|
||||
return cacheTransform;
|
||||
}
|
||||
}
|
||||
|
||||
public Transform HighlightPointRightHand
|
||||
{
|
||||
get
|
||||
{
|
||||
return rightHandSettings.highlightPoint == null ? rightHandSettings.interactPoint : rightHandSettings.highlightPoint;
|
||||
}
|
||||
}
|
||||
|
||||
public Transform HighlightPointLeftHand
|
||||
{
|
||||
get
|
||||
{
|
||||
return leftHandSettings.highlightPoint == null ? leftHandSettings.interactPoint : leftHandSettings.highlightPoint;
|
||||
}
|
||||
}
|
||||
|
||||
public Transform HighlightPointHandSettings
|
||||
{
|
||||
get
|
||||
{
|
||||
return handSettings.highlightPoint;
|
||||
}
|
||||
}
|
||||
|
||||
public Transform RightInteractPoint
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!shareHandInteractionSettings)
|
||||
return rightHandSettings.interactPoint;
|
||||
else
|
||||
return handSettings.interactPoint;
|
||||
}
|
||||
}
|
||||
|
||||
public Transform LeftInteractPoint
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!shareHandInteractionSettings)
|
||||
return rightHandSettings.interactPoint;
|
||||
else
|
||||
return handSettings.interactPoint;
|
||||
}
|
||||
}
|
||||
|
||||
public VR_HandInteractSettings HandSettings { get { return handSettings; } }
|
||||
public VR_HandInteractSettings RightHandSettings { get { return rightHandSettings; } }
|
||||
public VR_HandInteractSettings LeftHandSettings { get { return leftHandSettings; } }
|
||||
public VR_HandAnimationSettings HandAnimationSettings { get { return handAnimationSettings; ; } }
|
||||
public VR_HandAnimationSettings RightHandAnimationSettings { get { return rightHandAnimationSettings; } }
|
||||
public VR_HandAnimationSettings LeftHandAnimationSettings { get { return leftHandAnimationSettings; } }
|
||||
public VR_InputButton InteractButton { get { return interactButton; } }
|
||||
public Collider GrabCollider => grabCollider;
|
||||
|
||||
protected virtual void Awake()
|
||||
{
|
||||
|
||||
//if we dont use per hand settings set general settings as the settings for both hands
|
||||
if (shareHandInteractionSettings)
|
||||
{
|
||||
rightHandSettings = handSettings;
|
||||
leftHandSettings = handSettings;
|
||||
}
|
||||
|
||||
if (shareHandAnimationSettings)
|
||||
{
|
||||
rightHandAnimationSettings = handAnimationSettings;
|
||||
leftHandAnimationSettings = handAnimationSettings;
|
||||
}
|
||||
|
||||
//register this interactable
|
||||
VR_Manager.instance.RegisterInteract(this);
|
||||
|
||||
//create snap points if we need they
|
||||
CreateAllSnapPoints();
|
||||
}
|
||||
|
||||
protected virtual void Start()
|
||||
{
|
||||
CreateControllersInfo();
|
||||
}
|
||||
|
||||
private void CreateAllSnapPoints()
|
||||
{
|
||||
if (rightHandSettings.interactPoint == null)
|
||||
CreateSnapPoint(rightHandSettings);
|
||||
|
||||
if (leftHandSettings.interactPoint == null)
|
||||
CreateSnapPoint(leftHandSettings);
|
||||
|
||||
if (handSettings.interactPoint == null)
|
||||
CreateSnapPoint(handSettings);
|
||||
}
|
||||
|
||||
private void CreateSnapPoint(VR_HandInteractSettings settings)
|
||||
{
|
||||
settings.interactPoint = new GameObject("SnapPoint").transform;
|
||||
settings.interactPoint.parent = transform;
|
||||
settings.interactPoint.localPosition = Vector3.zero;
|
||||
settings.interactPoint.localRotation = Quaternion.identity;
|
||||
}
|
||||
|
||||
private void CreateControllersInfo()
|
||||
{
|
||||
rightControllerInfo = new VR_ControllerInfo(VR_Manager.instance.Player.RightController);
|
||||
leftControllerInfo = new VR_ControllerInfo(VR_Manager.instance.Player.LeftController);
|
||||
}
|
||||
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
//this object can be destroyed for 2 reasons
|
||||
//the programmer calling destroy on the gameobject
|
||||
// and the UnityEngine closing the game, so if Unity is closing the game
|
||||
//dont do nothing the game is just closing
|
||||
if (!VR_Manager.ApplicationIsQuitting)
|
||||
VR_Manager.instance.RemoveInteract(this);
|
||||
}
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
VR_Manager.instance.RegisterInteract(this);
|
||||
}
|
||||
|
||||
protected virtual void OnDestroy()
|
||||
{
|
||||
//this object can be destroyed for 2 reasons
|
||||
//the programmer calling destroy on the gameobject
|
||||
// and the UnityEngine closing the game, so if Unity is closing the game
|
||||
//dont do nothing the game is just closing
|
||||
if (!VR_Manager.ApplicationIsQuitting)
|
||||
VR_Manager.instance.RemoveInteract(this);
|
||||
}
|
||||
|
||||
protected virtual void Update()
|
||||
{
|
||||
if (!CanInteract) return;
|
||||
|
||||
ProcessControllerInfoInteraction(rightControllerInfo);
|
||||
ProcessControllerInfoInteraction(leftControllerInfo);
|
||||
}
|
||||
|
||||
private void ProcessControllerInfoInteraction(VR_ControllerInfo info)
|
||||
{
|
||||
if (info?.controller == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
VR_HandInteractSettings settings = info.controller.ControllerType == VR_ControllerType.Right ? rightHandSettings : leftHandSettings;
|
||||
Transform highlightPoint = info.controller.ControllerType == VR_ControllerType.Right ? HighlightPointRightHand : HighlightPointLeftHand;
|
||||
bool ignoreDistance = interactableType == InteractableType.Collider;
|
||||
|
||||
//if we are trying to do a distance grab using this controller
|
||||
if (!ignoreDistance && useDistanceGrab && activeDistanceGrabControllerList != null && activeDistanceGrabControllerList.Count > 0 && activeDistanceGrabControllerList.Contains(info.controller))
|
||||
{
|
||||
ignoreDistance = true;
|
||||
}
|
||||
|
||||
if (settings.canInteract && highlightPoint != null)
|
||||
{
|
||||
CheckIfShouldInteractWithController(info, ignoreDistance);
|
||||
}
|
||||
}
|
||||
|
||||
private void CheckIfShouldInteractWithController(VR_ControllerInfo info, bool ignoreDistance)
|
||||
{
|
||||
|
||||
float d = ignoreDistance ? 0.0f : GetDistanceToController(info.controller);
|
||||
|
||||
if (d <= interactDistance || ignoreDistance)
|
||||
{
|
||||
//the button was alredy pressed when the controller enter the grab range?
|
||||
if (info.interactionButtonWasPressed)
|
||||
{
|
||||
info.UpdateButtonWasPressed(interactButton);
|
||||
|
||||
if (info.interactionButtonWasPressed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (info.controller.enabled && info.controller.Input.GetButtonDown(interactButton))
|
||||
{
|
||||
info.controller.InteractWithNearesObject();
|
||||
info.interactionButtonWasPressed = true;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
info.UpdateButtonWasPressed(interactButton);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get the distance to the controller
|
||||
/// </summary>
|
||||
private float GetDistanceToController(VR_Controller controller)
|
||||
{
|
||||
float d = float.MaxValue;
|
||||
Transform interactPoint = controller.ControllerType == VR_ControllerType.Right ? HighlightPointRightHand : HighlightPointLeftHand;
|
||||
|
||||
if (controller.Input.IsConnected() && controller.CurrentGrab == null)
|
||||
{
|
||||
d = (interactPoint.position - controller.Position).magnitude;
|
||||
}
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
public virtual void Interact(VR_Controller controller)
|
||||
{
|
||||
onInteractEvent.Invoke(controller);
|
||||
}
|
||||
|
||||
public bool CanInteractUsingController(VR_Controller controller)
|
||||
{
|
||||
if (controller.ControllerType == VR_ControllerType.Right)
|
||||
return rightHandSettings.canInteract;
|
||||
if (controller.ControllerType == VR_ControllerType.Left)
|
||||
return leftHandSettings.canInteract;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public VR_HandInteractSettings GetHandInteractionSettings(VR_Controller controller)
|
||||
{
|
||||
if (controller.ControllerType == VR_ControllerType.Right)
|
||||
return rightHandSettings;
|
||||
if (controller.ControllerType == VR_ControllerType.Left)
|
||||
return leftHandSettings;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public VR_HandAnimationSettings GetHandAnimationSettings(VR_Controller controller)
|
||||
{
|
||||
if (controller.ControllerType == VR_ControllerType.Right)
|
||||
return rightHandAnimationSettings;
|
||||
if (controller.ControllerType == VR_ControllerType.Left)
|
||||
return leftHandAnimationSettings;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void SetInteractDistanceViaInspector(float d)
|
||||
{
|
||||
interactDistance = d;
|
||||
}
|
||||
|
||||
public void AddActiveDistanceGrabController(VR_Controller controller)
|
||||
{
|
||||
if (!useDistanceGrab)
|
||||
return;
|
||||
|
||||
activeDistanceGrabControllerList.Add(controller);
|
||||
}
|
||||
|
||||
public void RemoveActiveDistanceGrabController(VR_Controller controller)
|
||||
{
|
||||
if (!useDistanceGrab)
|
||||
return;
|
||||
|
||||
activeDistanceGrabControllerList.Remove(controller);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class VR_ControllerInfo
|
||||
{
|
||||
public VR_Controller controller = null;
|
||||
public bool interactionButtonWasPressed = false;
|
||||
|
||||
public VR_ControllerInfo(VR_Controller controller)
|
||||
{
|
||||
this.controller = controller;
|
||||
interactionButtonWasPressed = false;
|
||||
}
|
||||
|
||||
public void UpdateButtonWasPressed(VR_InputButton interactButton)
|
||||
{
|
||||
interactionButtonWasPressed = controller.Input.GetButtonDown(interactButton);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user