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,36 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace VRBeats
|
||||
{
|
||||
public enum Direction
|
||||
{
|
||||
UpperLeft = 0,
|
||||
Up,
|
||||
UpperRight,
|
||||
Left,
|
||||
Center,
|
||||
Right,
|
||||
LowerLeft,
|
||||
Down,
|
||||
LowerRight
|
||||
}
|
||||
|
||||
public enum ColorSide
|
||||
{
|
||||
Left,
|
||||
Right
|
||||
}
|
||||
|
||||
|
||||
[System.Serializable]
|
||||
public class SpawnEventInfo
|
||||
{
|
||||
public Direction hitDirection = Direction.Up;
|
||||
public ColorSide colorSide = ColorSide.Right;
|
||||
public bool useSpark = true;
|
||||
public Vector3 position = Vector3.zero;
|
||||
public Vector3 rotation = Vector3.zero;
|
||||
public float speed = 2.0f;
|
||||
public int speedMultiplier = 1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0306981eca736184985aa56ff8f27554
|
||||
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/Scripts/Spawneable/SpawnEventInfo.cs
|
||||
uploadId: 546658
|
||||
@@ -0,0 +1,115 @@
|
||||
using UnityEngine;
|
||||
|
||||
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
#endif
|
||||
|
||||
namespace VRBeats
|
||||
{
|
||||
public class Spawneable : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private float speed = 2.0f;
|
||||
[SerializeField] private Vector3 rotation = Vector3.zero;
|
||||
|
||||
public float Speed { get { return speed; } }
|
||||
|
||||
private bool updatePositionX = false;
|
||||
private bool updatePositionY = false;
|
||||
private bool updatePositionZ = false;
|
||||
private bool updateSpeed = false;
|
||||
private bool updateRotation = false;
|
||||
|
||||
public System.Action onSpawnComplete;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
public virtual void CustomInspector(SpawnEventInfo info, Object[] targets)
|
||||
{
|
||||
EditorGUI.BeginChangeCheck();
|
||||
Vector3 lastPosition = info.position;
|
||||
info.position = EditorGUILayout.Vector3Field("Position", info.position);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
if (lastPosition.x != info.position.x)
|
||||
updatePositionX = true;
|
||||
else if (lastPosition.y != info.position.y)
|
||||
updatePositionY = true;
|
||||
else if (lastPosition.z != info.position.z)
|
||||
updatePositionZ = true;
|
||||
}
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
info.speed = EditorGUILayout.FloatField("Speed", info.speed);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
updateSpeed = true;
|
||||
}
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
info.rotation = EditorGUILayout.Vector3Field("Rotation" , info.rotation);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
updateRotation = true;
|
||||
}
|
||||
|
||||
if (info.speed < 0.0001f)
|
||||
{
|
||||
info.speed = 0.0001f;
|
||||
}
|
||||
|
||||
foreach (Object obj in targets)
|
||||
{
|
||||
if (obj is VR_BeatSpawnMarker spawnMarker)
|
||||
{
|
||||
if (updateSpeed)
|
||||
{
|
||||
spawnMarker.spawInfo.speed = info.speed;
|
||||
}
|
||||
|
||||
|
||||
if (updatePositionX)
|
||||
spawnMarker.spawInfo.position.x = info.position.x;
|
||||
if (updatePositionY)
|
||||
spawnMarker.spawInfo.position.y = info.position.y;
|
||||
if (updatePositionZ)
|
||||
spawnMarker.spawInfo.position.z = info.position.z;
|
||||
|
||||
if (updateRotation)
|
||||
spawnMarker.spawInfo.rotation = info.rotation;
|
||||
}
|
||||
}
|
||||
|
||||
updatePositionX = false;
|
||||
updatePositionY = false;
|
||||
updatePositionZ = false;
|
||||
updateRotation = false;
|
||||
updateSpeed = false;
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
public virtual Quaternion GetSpawnRotation()
|
||||
{
|
||||
return Quaternion.Euler(rotation);
|
||||
}
|
||||
|
||||
public virtual void Construct(SpawnEventInfo info)
|
||||
{
|
||||
speed = info.speed * info.speedMultiplier;
|
||||
}
|
||||
|
||||
public virtual void OnSpawn()
|
||||
{
|
||||
if (onSpawnComplete != null)
|
||||
onSpawnComplete.Invoke();
|
||||
}
|
||||
|
||||
public void SetSpeedDirection(int dir)
|
||||
{
|
||||
speed = Mathf.Abs(speed) * dir;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6e04755e95693e745b8825af30c3ce94
|
||||
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/Scripts/Spawneable/Spawneable.cs
|
||||
uploadId: 546658
|
||||
@@ -0,0 +1,184 @@
|
||||
using UnityEngine;
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
#endif
|
||||
|
||||
namespace VRBeats
|
||||
{
|
||||
public class VR_BeatCubeSpawneable : Spawneable
|
||||
{
|
||||
[SerializeField] private GameObject arrow = null;
|
||||
[SerializeField] private GameObject dot = null;
|
||||
[SerializeField] private Spark sparkPrefab = null;
|
||||
[SerializeField] private ColorSide colorSide = ColorSide.Left;
|
||||
[SerializeField] private bool useSpark = false;
|
||||
|
||||
public ColorSide ColorSide { get { return colorSide; } }
|
||||
public Direction HitDirection { get { return hitDirection; } }
|
||||
|
||||
private Direction hitDirection = Direction.Center;
|
||||
|
||||
public override void OnSpawn()
|
||||
{
|
||||
base.OnSpawn();
|
||||
|
||||
if (useSpark)
|
||||
{
|
||||
if (sparkPrefab == null) return;
|
||||
|
||||
Color desireColor = VR_BeatManager.instance.GetColorFromColorSide(colorSide);
|
||||
Spark spark = Instantiate(sparkPrefab, transform.position, Quaternion.identity);
|
||||
spark.transform.parent = transform;
|
||||
spark.Construct(desireColor);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public override void Construct(SpawnEventInfo info)
|
||||
{
|
||||
base.Construct(info);
|
||||
|
||||
transform.rotation = CalculateRotationFromDirection(info.hitDirection);
|
||||
colorSide = info.colorSide;
|
||||
useSpark = info.useSpark;
|
||||
hitDirection = info.hitDirection;
|
||||
|
||||
//use the arrow of the center
|
||||
arrow.SetActive( info.hitDirection != Direction.Center );
|
||||
dot.SetActive( info.hitDirection == Direction.Center );
|
||||
|
||||
}
|
||||
|
||||
|
||||
private Quaternion CalculateRotationFromDirection(Direction dir)
|
||||
{
|
||||
Vector3 rot = Vector3.zero;
|
||||
|
||||
if (dir == Direction.Up)
|
||||
{
|
||||
rot = new Vector3(0.0f, 0.0f, 0.0f);
|
||||
}
|
||||
else if (dir == Direction.UpperRight)
|
||||
{
|
||||
rot = new Vector3(0.0f, 0.0f, -45.0f);
|
||||
}
|
||||
else if (dir == Direction.Right)
|
||||
{
|
||||
rot = new Vector3(0.0f, 0.0f, -90.0f);
|
||||
}
|
||||
else if (dir == Direction.LowerRight)
|
||||
{
|
||||
rot = new Vector3(0.0f, 0.0f, -135.0f);
|
||||
}
|
||||
else if (dir == Direction.Down)
|
||||
{
|
||||
rot = new Vector3(0.0f, 0.0f, -180.0f);
|
||||
}
|
||||
|
||||
else if (dir == Direction.LowerLeft)
|
||||
{
|
||||
rot = new Vector3(0.0f, 0.0f, -225.0f);
|
||||
}
|
||||
else if (dir == Direction.Left)
|
||||
{
|
||||
rot = new Vector3(0.0f, 0.0f, -270.0f);
|
||||
}
|
||||
else if (dir == Direction.UpperLeft)
|
||||
{
|
||||
rot = new Vector3(0.0f, 0.0f, -315.0f);
|
||||
}
|
||||
|
||||
|
||||
return Quaternion.Euler(rot);
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
|
||||
string[] textureNameArray = { "upperLeft", "up", "upperRight", "left", "center", "right", "lowerLeft", "down", "lowerRight" };
|
||||
Texture[] texArray = null;
|
||||
|
||||
private bool updateHitDir = false;
|
||||
private bool updateUseSpark = false;
|
||||
private bool updateColorSide = false;
|
||||
|
||||
|
||||
private void LoadArrowTextures()
|
||||
{
|
||||
|
||||
texArray = new Texture[textureNameArray.Length];
|
||||
for (int n = 0; n < texArray.Length; n++)
|
||||
{
|
||||
texArray[n] = Resources.Load("Editor/Arrow/" + textureNameArray[n]) as Texture;
|
||||
}
|
||||
}
|
||||
|
||||
public override void CustomInspector(SpawnEventInfo info , Object[] targets)
|
||||
{
|
||||
EditorGUI.BeginChangeCheck();
|
||||
|
||||
LoadArrowTextures();
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
info.hitDirection = DrawArrowGridInspector("" , info.hitDirection);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
updateHitDir = true;
|
||||
}
|
||||
|
||||
base.CustomInspector(info , targets);
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
info.useSpark = EditorGUILayout.Toggle("Use Spark" , info.useSpark);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
updateUseSpark = true;
|
||||
}
|
||||
|
||||
EditorGUI.BeginChangeCheck();
|
||||
info.colorSide = (ColorSide) EditorGUILayout.EnumPopup("Color Side" , info.colorSide);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
updateColorSide = true;
|
||||
}
|
||||
|
||||
/*manual assignment here, remember to check that the selected objects
|
||||
are in fact of the appropriate type.*/
|
||||
foreach (Object obj in targets)
|
||||
{
|
||||
if (obj is VR_BeatSpawnMarker spawnMarker)
|
||||
{
|
||||
if (updateHitDir)
|
||||
spawnMarker.spawInfo.hitDirection = info.hitDirection;
|
||||
|
||||
else if (updateUseSpark)
|
||||
spawnMarker.spawInfo.useSpark = info.useSpark;
|
||||
|
||||
else if (updateColorSide)
|
||||
spawnMarker.spawInfo.colorSide = info.colorSide;
|
||||
}
|
||||
}
|
||||
|
||||
updateHitDir = false;
|
||||
updateColorSide = false;
|
||||
updateUseSpark = false;
|
||||
|
||||
}
|
||||
|
||||
private Direction DrawArrowGridInspector(string label, Direction dir)
|
||||
{
|
||||
EditorGUILayout.LabelField(label, EditorStyles.boldLabel);
|
||||
GUILayout.BeginVertical("Box");
|
||||
|
||||
dir = (Direction)GUILayout.SelectionGrid((int)dir, texArray, 3, GUILayout.ExpandWidth(false), GUILayout.MaxHeight(150f), GUILayout.MaxWidth(150f));
|
||||
GUILayout.EndVertical();
|
||||
|
||||
return dir;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8112f3076d75f4648939288b5636aa7d
|
||||
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/Scripts/Spawneable/VR_BeatCubeSpawneable.cs
|
||||
uploadId: 546658
|
||||
Reference in New Issue
Block a user