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:
2026-05-21 23:37:34 +09:00
commit 4dad9e5d5b
1068 changed files with 175146 additions and 0 deletions
@@ -0,0 +1,38 @@
using UnityEngine;
namespace VRSDK
{
/// <summary>
/// Supported Inputs
/// </summary>
public enum VR_InputButton
{
None,
Primary,
Secondary,
Trigger,
Grip,
TumbstickPress
}
public abstract class VR_InputDevice
{
protected VR_Controller InputController { get; private set; }
public VR_InputDevice(VR_Controller controller)
{
this.InputController = controller;
}
public abstract Quaternion GetRotationOffset();
public abstract Vector3 GetPositionOffset();
public abstract string GetDeviceName();
public abstract float GetAxis1D(VR_InputButton button);
public abstract Vector2 GetJoystick();
public abstract bool GetButtonDown(VR_InputButton button);
public abstract bool GetButtonUp(VR_InputButton button);
public abstract bool GetButton(VR_InputButton button);
public abstract bool IsConnected();
public abstract System.Enum GetControllerType();
}
}
@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 14fe470127ef83b49901491fcbd88dac
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 168243
packageName: VR Beats Kit
packageVersion: 2.0
assetPath: Assets/VRBeatsKit/Modules/VRSDK/VR/Input/VR_InputDevice.cs
uploadId: 546658
@@ -0,0 +1,159 @@
using System;
using UnityEngine;
namespace VRSDK
{
public class VR_OculusInput : VR_InputDevice
{
#if SDK_OCULUS
private OVRInput.Controller OVRControllerType
{
get
{
return InputController.ControllerType == VR_ControllerType.Right ? OVRInput.Controller.RTouch : OVRInput.Controller.LTouch;
}
}
#endif
public VR_OculusInput(VR_Controller controller) : base(controller) { }
public override float GetAxis1D(VR_InputButton button)
{
#if SDK_OCULUS
OVRInput.Axis1D axis;
switch (button)
{
case VR_InputButton.Trigger:
axis = OVRInput.Axis1D.PrimaryIndexTrigger;
return OVRInput.Get(axis, OVRControllerType);
case VR_InputButton.Grip:
axis = OVRInput.Axis1D.PrimaryHandTrigger;
return OVRInput.Get(axis, OVRControllerType);
}
#endif
return 0.0f;
}
public override bool GetButton(VR_InputButton button)
{
#if SDK_OCULUS
switch (button)
{
case VR_InputButton.Grip:
return GetAxis1D( button ) > 0.25f;
case VR_InputButton.Trigger:
return GetAxis1D( button ) > 0.25f;
case VR_InputButton.Primary:
return OVRInput.Get(OVRInput.Button.One, OVRControllerType);
case VR_InputButton.Secondary:
return OVRInput.Get(OVRInput.Button.Two, OVRControllerType);
case VR_InputButton.TumbstickPress:
return OVRInput.Get(OVRInput.Button.PrimaryThumbstick, OVRControllerType);
}
#endif
return false;
}
public override bool GetButtonDown(VR_InputButton button)
{
#if SDK_OCULUS
switch (button)
{
case VR_InputButton.Grip:
return OVRInput.GetDown( OVRInput.Button.PrimaryHandTrigger , OVRControllerType );
case VR_InputButton.Trigger:
return OVRInput.GetDown(OVRInput.Button.PrimaryIndexTrigger, OVRControllerType);
case VR_InputButton.Primary:
return OVRInput.GetDown(OVRInput.Button.One, OVRControllerType);
case VR_InputButton.Secondary:
return OVRInput.GetDown(OVRInput.Button.Two, OVRControllerType);
case VR_InputButton.TumbstickPress:
return OVRInput.GetDown(OVRInput.Button.PrimaryThumbstick, OVRControllerType);
}
#endif
return false;
}
public override bool GetButtonUp(VR_InputButton button)
{
#if SDK_OCULUS
switch (button)
{
case VR_InputButton.Grip:
return OVRInput.GetUp(OVRInput.Button.PrimaryHandTrigger, OVRControllerType);
case VR_InputButton.Trigger:
return OVRInput.GetUp(OVRInput.Button.PrimaryIndexTrigger, OVRControllerType);
case VR_InputButton.Primary:
return OVRInput.GetUp(OVRInput.Button.One, OVRControllerType);
case VR_InputButton.Secondary:
return OVRInput.GetUp(OVRInput.Button.Two, OVRControllerType);
case VR_InputButton.TumbstickPress:
return OVRInput.GetUp(OVRInput.Button.PrimaryThumbstick, OVRControllerType);
}
#endif
return false;
}
public override string GetDeviceName()
{
#if SDK_OCULUS
return OVRControllerType.ToString();
#endif
return "";
}
public override Vector2 GetJoystick()
{
#if SDK_OCULUS
OVRInput.Axis2D axis = OVRInput.Axis2D.PrimaryThumbstick;
return OVRInput.Get(axis, OVRControllerType);
#endif
return Vector2.zero;
}
public override bool IsConnected()
{
#if SDK_OCULUS
return OVRInput.IsControllerConnected(OVRControllerType);
#endif
return false;
}
public override Quaternion GetRotationOffset()
{
#if SDK_OCULUS
return Quaternion.identity;
#endif
return Quaternion.identity;
}
public override Vector3 GetPositionOffset()
{
return Vector3.zero;
}
public override Enum GetControllerType()
{
#if SDK_OCULUS
return OVRControllerType;
#endif
return default;
}
}
}
@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: eb89955c58e54484cb2cfea809091f76
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 168243
packageName: VR Beats Kit
packageVersion: 2.0
assetPath: Assets/VRBeatsKit/Modules/VRSDK/VR/Input/VR_OculusInput.cs
uploadId: 546658
@@ -0,0 +1,180 @@
using System;
using UnityEngine;
#if SDK_STEAM_VR
using Valve.VR;
#endif
namespace VRSDK
{
public class VR_SteamVRInput : VR_InputDevice
{
#if SDK_STEAM_VR
private SteamVR_Action_Single grabAction = null;
private SteamVR_Action_Boolean triggerAction = null;
private SteamVR_Action_Boolean primaryButtonAction = null;
private SteamVR_Action_Boolean secondaryButtonAction = null;
private SteamVR_Action_Boolean joystickPressAction = null;
private SteamVR_Action_Vector2 joystickInputAction = null;
public SteamVR_Input_Sources SteamControllerType { get { return InputController.ControllerType == VR_ControllerType.Right ? SteamVR_Input_Sources.RightHand : SteamVR_Input_Sources.LeftHand; } }
private bool isConnected = false;
#endif
public VR_SteamVRInput(VR_Controller controller) : base(controller)
{
#if SDK_STEAM_VR
InitializeSteamVR_Actions();
SteamVR_Behaviour_Pose steamController = controller.GetComponentInParent<SteamVR_Behaviour_Pose>();
steamController.onConnectedChanged.AddListener(delegate (SteamVR_Behaviour_Pose poseController, SteamVR_Input_Sources sources, bool state) { isConnected = state; });
#endif
}
#if SDK_STEAM_VR
private void InitializeSteamVR_Actions()
{
grabAction = SteamVR_Input.GetAction<SteamVR_Action_Single>("VRShooterKit", "Grab");
triggerAction = SteamVR_Input.GetAction<SteamVR_Action_Boolean>("VRShooterKit", "Shoot");
primaryButtonAction = SteamVR_Input.GetAction<SteamVR_Action_Boolean>("VRShooterKit", "PrimaryButton");
secondaryButtonAction = SteamVR_Input.GetAction<SteamVR_Action_Boolean>("VRShooterKit", "SecondaryButton");
joystickPressAction = SteamVR_Input.GetAction<SteamVR_Action_Boolean>("VRShooterKit", "JoystickPress");
joystickInputAction = SteamVR_Input.GetAction<SteamVR_Action_Vector2>("VRShooterKit", "Joystick");
}
#endif
public override float GetAxis1D(VR_InputButton button)
{
#if SDK_STEAM_VR
switch (button)
{
case VR_InputButton.Trigger:
return GetButton(button) ? 1.0f : 0.0f;
case VR_InputButton.Grip:
return grabAction.GetAxis(SteamControllerType);
}
#endif
return 0.0f;
}
public override bool GetButton(VR_InputButton button)
{
#if SDK_STEAM_VR
switch (button)
{
case VR_InputButton.Trigger:
return triggerAction.GetState(SteamControllerType);
case VR_InputButton.Grip:
return grabAction.GetAxis(SteamControllerType) > 0.65f;
case VR_InputButton.Primary:
return primaryButtonAction.GetState(SteamControllerType);
case VR_InputButton.Secondary:
return secondaryButtonAction.GetState(SteamControllerType);
case VR_InputButton.TumbstickPress:
return joystickPressAction.GetState(SteamControllerType);
}
#endif
return false;
}
public override bool GetButtonDown(VR_InputButton button)
{
#if SDK_STEAM_VR
switch (button)
{
case VR_InputButton.Trigger:
return triggerAction.GetStateDown(SteamControllerType);
case VR_InputButton.Grip:
return grabAction.GetAxis(SteamControllerType) > 0.65f;
case VR_InputButton.Primary:
return primaryButtonAction.GetStateDown(SteamControllerType);
case VR_InputButton.Secondary:
return secondaryButtonAction.GetStateDown(SteamControllerType);
case VR_InputButton.TumbstickPress:
return joystickPressAction.GetStateDown(SteamControllerType);
}
#endif
return false;
}
public override bool GetButtonUp(VR_InputButton button)
{
#if SDK_STEAM_VR
switch (button)
{
case VR_InputButton.Trigger:
return triggerAction.GetStateUp(SteamControllerType);
case VR_InputButton.Grip:
return grabAction.GetAxis(SteamControllerType) > 0.65f;
case VR_InputButton.Primary:
return primaryButtonAction.GetStateUp(SteamControllerType);
case VR_InputButton.Secondary:
return secondaryButtonAction.GetStateUp(SteamControllerType);
case VR_InputButton.TumbstickPress:
return joystickPressAction.GetStateUp(SteamControllerType);
}
#endif
return false;
}
public override string GetDeviceName()
{
#if SDK_STEAM_VR
return SteamControllerType.ToString();
#endif
return "";
}
public override Vector2 GetJoystick()
{
#if SDK_STEAM_VR
return joystickInputAction.GetAxis(SteamControllerType);
#endif
return Vector2.zero;
}
public override bool IsConnected()
{
#if SDK_STEAM_VR
return isConnected;
#endif
return false;
}
public override Quaternion GetRotationOffset()
{
return Quaternion.identity;
}
public override Vector3 GetPositionOffset()
{
return Vector3.zero;
}
public override Enum GetControllerType()
{
#if SDK_STEAM_VR
return SteamControllerType;
#endif
return default;
}
}
}
@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 1a75ba2a8a91f6e48a3bb20cd56723a3
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 168243
packageName: VR Beats Kit
packageVersion: 2.0
assetPath: Assets/VRBeatsKit/Modules/VRSDK/VR/Input/VR_SteamVRInput.cs
uploadId: 546658
@@ -0,0 +1,161 @@
using UnityEngine;
using System.Collections.Generic;
using System;
#if UNITY_XR
using UnityEngine.XR.Interaction.Toolkit;
using UnityEngine.XR;
#endif
namespace VRSDK
{
public class VR_XRInput : VR_InputDevice
{
private InputDevice thisInputDevice;
private XRInputHelper inputHelper = null;
private List<VR_InputButton> inputButtonTrackedList = new List<VR_InputButton>()
{
VR_InputButton.Grip ,
VR_InputButton.Primary ,
VR_InputButton.Secondary ,
VR_InputButton.Trigger ,
VR_InputButton.TumbstickPress
};
public VR_XRInput(VR_Controller controller) : base(controller)
{
GameObject go = new GameObject( "XRInputHelper" );
inputHelper = go.AddComponent<XRInputHelper>();
inputHelper.Construct(this , inputButtonTrackedList);
InputDevices.deviceConnected += RegisterDevice;
List<InputDevice> devices = new List<InputDevice>();
InputDevices.GetDevices(devices);
for (int i = 0; i < devices.Count; i++)
RegisterDevice(devices[i]);
}
private void RegisterDevice(InputDevice connectedDevice)
{
if (IsValidInputDeviceForController(InputController, connectedDevice))
{
thisInputDevice = connectedDevice;
}
}
private bool IsValidInputDeviceForController(VR_Controller controller , InputDevice inputDevice)
{
if (controller.ControllerType == VR_ControllerType.Right)
{
return InputDeviceIsRightController(inputDevice);
}
else
{
return InputDeviceIsLeftController(inputDevice);
}
}
private bool InputDeviceIsRightController(InputDevice inputDevice)
{
return (inputDevice.characteristics & InputDeviceCharacteristics.Right) != 0;
}
private bool InputDeviceIsLeftController(InputDevice inputDevice)
{
return (inputDevice.characteristics & InputDeviceCharacteristics.Left) != 0;
}
public override float GetAxis1D(VR_InputButton button)
{
float value = 0.0f;
switch (button)
{
case VR_InputButton.Trigger:
thisInputDevice.TryGetFeatureValue(CommonUsages.trigger, out value);
break;
case VR_InputButton.Grip:
thisInputDevice.TryGetFeatureValue(CommonUsages.grip, out value);
break;
}
return value;
}
public override bool GetButton(VR_InputButton button)
{
bool value = false;
switch (button)
{
case VR_InputButton.Grip:
return GetAxis1D(button) > 0.25f;
case VR_InputButton.Trigger:
return GetAxis1D(button) > 0.25f;
case VR_InputButton.Primary:
#if UNITY_XR
thisInputDevice.IsPressed(InputHelpers.Button.PrimaryButton, out value);
#endif
break;
case VR_InputButton.Secondary:
#if UNITY_XR
thisInputDevice.IsPressed(InputHelpers.Button.SecondaryButton, out value);
#endif
break;
case VR_InputButton.TumbstickPress:
#if UNITY_XR
thisInputDevice.IsPressed(InputHelpers.Button.Primary2DAxisClick, out value);
#endif
break;
}
return value;
}
public override bool GetButtonDown(VR_InputButton button)
{
return inputHelper.GetButtonDown(button);
}
public override bool GetButtonUp(VR_InputButton button)
{
return inputHelper.GetButtonUp(button);
}
public override string GetDeviceName()
{
return thisInputDevice.name;
}
public override Vector2 GetJoystick()
{
Vector2 joystick;
thisInputDevice.TryGetFeatureValue(CommonUsages.primary2DAxis, out joystick);
return joystick;
}
public override Vector3 GetPositionOffset()
{
return Vector3.zero;
}
public override Quaternion GetRotationOffset()
{
return Quaternion.identity;
}
public override bool IsConnected()
{
return true;
}
public override Enum GetControllerType()
{
return default;
}
}
}
@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 87cb4b9deb8252b4e957bdb497a4df0d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 168243
packageName: VR Beats Kit
packageVersion: 2.0
assetPath: Assets/VRBeatsKit/Modules/VRSDK/VR/Input/VR_XRInput.cs
uploadId: 546658
@@ -0,0 +1,76 @@
using UnityEngine;
using System.Collections.Generic;
using VRSDK.Collections;
namespace VRSDK
{
public class XRInputHelper : MonoBehaviour
{
private List<VR_InputButton> trackingButtonList = null;
private Dictionary<VR_InputButton, Buffer<bool>> buttonStateHistory = new Dictionary<VR_InputButton, Buffer<bool>>();
private int historySize = 3;
private VR_InputDevice input = null;
public void Construct(VR_InputDevice input , List<VR_InputButton> trackingButtonList)
{
this.input = input;
this.trackingButtonList = trackingButtonList;
SetupButtonInfo();
}
private void SetupButtonInfo()
{
for (int n = 0; n < trackingButtonList.Count; n++)
{
buttonStateHistory.Add( trackingButtonList[n] , new Buffer<bool>(historySize) );
}
}
private void Update()
{
for (int n = 0; n < trackingButtonList.Count; n++)
{
Buffer<bool> buffer;
if ( buttonStateHistory.TryGetValue( trackingButtonList[n] , out buffer ) )
{
buffer.Add( input.GetButton(trackingButtonList[n]) );
}
}
}
public bool GetButtonDown(VR_InputButton button)
{
Buffer<bool> buffer;
if (buttonStateHistory.TryGetValue(button, out buffer))
{
if (buffer.Count >= historySize && !buffer[historySize - 2] && input.GetButton(button))
return true;
}
return false;
}
public bool GetButtonUp(VR_InputButton button)
{
Buffer<bool> buffer;
if (buttonStateHistory.TryGetValue(button, out buffer))
{
if (buffer.Count >= historySize && buffer[historySize - 2] && !input.GetButton(button))
return true;
}
return false;
}
}
public struct XRButtonInfo
{
public VR_InputButton button;
public bool state;
}
}
@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 62c8e9cfab020e64fbc32ff805442af3
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
AssetOrigin:
serializedVersion: 1
productId: 168243
packageName: VR Beats Kit
packageVersion: 2.0
assetPath: Assets/VRBeatsKit/Modules/VRSDK/VR/Input/XRInputHelper.cs
uploadId: 546658