Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions Assets/Audio.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions Assets/Audio/SFX.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Binary file added Assets/Audio/SFX/ButtonHit.wav
Binary file not shown.
23 changes: 23 additions & 0 deletions Assets/Audio/SFX/ButtonHit.wav.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Binary file added Assets/Audio/SFX/CorrectHit.wav
Binary file not shown.
23 changes: 23 additions & 0 deletions Assets/Audio/SFX/CorrectHit.wav.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Binary file added Assets/Audio/SFX/IncorrectHit.wav
Binary file not shown.
23 changes: 23 additions & 0 deletions Assets/Audio/SFX/IncorrectHit.wav.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Binary file added Assets/Audio/SFX/MissHit.wav
Binary file not shown.
23 changes: 23 additions & 0 deletions Assets/Audio/SFX/MissHit.wav.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Binary file added Assets/Audio/SFX/WrongDirection.wav
Binary file not shown.
23 changes: 23 additions & 0 deletions Assets/Audio/SFX/WrongDirection.wav.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions Assets/Integration.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

220 changes: 220 additions & 0 deletions Assets/Integration/DebugPrototypeController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,220 @@
using TMPro;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

/** <summary>
* Prototype debug panel. Forces 16:9 aspect ratio via camera viewport.
* </summary>
*/
public class DebugPrototypeController : MonoBehaviour
{
#region Inspector Fields — Scriptable Objects

[Header("Scriptable Objects")]
[Tooltip("Controls note appearance timing (note appearance beats slider).")]
[SerializeField] private RhythmVisualConfig _rhythmVisualConfig;

#endregion

#region Inspector Fields — Note Appearance Beats

[Header("Note Appearance Beats")]
[Tooltip("Slider that sets RhythmVisualConfig.NoteAppearanceBeats. " +
"Higher value = notes appear further ahead = more reaction time.")]
[SerializeField] private Slider _noteBeatsSlider;
[Tooltip("Optional label displaying the current beats value.")]
[SerializeField] private TMP_Text _noteBeatsLabel;
[Tooltip("Minimum note appearance beats.")]
[SerializeField] private float _noteBeatsMin = 0.5f;
[Tooltip("Maximum note appearance beats.")]
[SerializeField] private float _noteBeatsMax = 6f;

#endregion

#region Inspector Fields — Tree Preview

[Header("Tree Preview")]
[Tooltip("The CameraRig driving gameplay camera movement.")]
[SerializeField] private CameraRig _cameraRig;
[Tooltip("Slider that zooms Camera.main back along Z for a tree overview.")]
[SerializeField] private Slider _cameraZSlider;
[Tooltip("Optional label displaying the current camera Z value.")]
[SerializeField] private TMP_Text _cameraZLabel;
[Tooltip("Background plane whose XY scale is adjusted proportionally as the camera moves back.")]
[SerializeField] private Transform _backgroundPlane;

#endregion

#region Inspector Fields — Controls

[Header("Controls")]
[Tooltip("Reloads the scene at the specified build index.")]
[SerializeField] private Button _restartButton;
[Tooltip("Build index of the scene to load on restart.")]
[SerializeField] private int _gameSceneIndex;

#endregion

#region Private State

private Camera _mainCamera;
private float _initialCameraZ;
private Vector3 _basePlaneScale;

#endregion

#region Lifecycle

private void Awake()
{
ApplyAspectRatio();
SetupNoteBeatsSlider();
SetupCameraZSlider();
SetupRestartButton();
}

private void Start()
{
InitializeCameraPreview();
}

private void OnDestroy()
{
if (_cameraRig != null)
_cameraRig.OnGameplayMoved -= OnGameplayMoved;
}

#endregion

#region Setup

private void ApplyAspectRatio()
{
Camera cam = Camera.main;
if (cam == null) return;

float targetAspect = 16f / 9f;
float windowAspect = (float)Screen.width / Screen.height;

if (windowAspect > targetAspect)
{
float scaleWidth = targetAspect / windowAspect;
cam.rect = new Rect((1f - scaleWidth) * 0.5f, 0f, scaleWidth, 1f);
}
else
{
float scaleHeight = windowAspect / targetAspect;
cam.rect = new Rect(0f, (1f - scaleHeight) * 0.5f, 1f, scaleHeight);
}
}

private void SetupNoteBeatsSlider()
{
if (_noteBeatsSlider == null) return;

_noteBeatsSlider.minValue = _noteBeatsMin;
_noteBeatsSlider.maxValue = _noteBeatsMax;
_noteBeatsSlider.value = _rhythmVisualConfig != null
? _rhythmVisualConfig.NoteAppearanceBeats
: 2f;

_noteBeatsSlider.onValueChanged.AddListener(OnNoteBeatsChanged);
RefreshNoteBeatsLabel(_noteBeatsSlider.value);
}

private void SetupCameraZSlider()
{
if (_cameraZSlider == null) return;

_cameraZSlider.minValue = 0f;
_cameraZSlider.maxValue = 1f;
_cameraZSlider.value = 0f;
_cameraZSlider.onValueChanged.AddListener(OnCameraZChanged);
}

/** <summary>
* Deferred to Start so CameraRig.Initialize (called in game controller Awake) has
* already positioned the camera before we snapshot the initial Z.
* </summary>
*/
private void InitializeCameraPreview()
{
_mainCamera = Camera.main;
if (_mainCamera == null) return;

_initialCameraZ = _mainCamera.transform.position.z;

if (_backgroundPlane != null)
_basePlaneScale = _backgroundPlane.localScale;

RefreshCameraZLabel();

if (_cameraRig != null)
_cameraRig.OnGameplayMoved += OnGameplayMoved;
}

private void SetupRestartButton()
{
if (_restartButton == null) return;
_restartButton.onClick.AddListener(OnRestartClicked);
}

#endregion

#region Callbacks

private void OnNoteBeatsChanged(float value)
{
if (_rhythmVisualConfig != null)
_rhythmVisualConfig.NoteAppearanceBeats = value;

RefreshNoteBeatsLabel(value);
}

private void OnCameraZChanged(float value)
{
if (_mainCamera == null || Mathf.Approximately(_initialCameraZ, 0f)) return;

float newZ = _initialCameraZ * (1f + value);

Vector3 pos = _mainCamera.transform.position;
pos.z = newZ;
_mainCamera.transform.position = pos;

if (_backgroundPlane != null)
_backgroundPlane.localScale = _basePlaneScale * (newZ / _initialCameraZ);

RefreshCameraZLabel();
}

private void OnGameplayMoved()
{
if (_cameraZSlider != null)
_cameraZSlider.SetValueWithoutNotify(0f);

if (_backgroundPlane != null)
_backgroundPlane.localScale = _basePlaneScale;

RefreshCameraZLabel();
}

private void OnRestartClicked()
{
SceneManager.LoadScene(_gameSceneIndex);
}

private void RefreshNoteBeatsLabel(float value)
{
if (_noteBeatsLabel != null)
_noteBeatsLabel.text = $"Note Speed: {value:F2} beats";
}

private void RefreshCameraZLabel()
{
if (_cameraZLabel != null)
_cameraZLabel.text = $"Preview Zoom: {_cameraZSlider.value * 100f:F0}%";
}

#endregion
}
2 changes: 2 additions & 0 deletions Assets/Integration/DebugPrototypeController.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading