diff --git a/src/HitTheKit.Unity/Assets/HitTheKit/Runtime/Gameplay/GameplayAudioFeedback.cs b/src/HitTheKit.Unity/Assets/HitTheKit/Runtime/Gameplay/GameplayAudioFeedback.cs index 52e08d0..afdf570 100644 --- a/src/HitTheKit.Unity/Assets/HitTheKit/Runtime/Gameplay/GameplayAudioFeedback.cs +++ b/src/HitTheKit.Unity/Assets/HitTheKit/Runtime/Gameplay/GameplayAudioFeedback.cs @@ -25,8 +25,10 @@ public static GameplayAudioFeedbackDecision ForInput(DrumInputEvent input, HitRe // A physical electronic kit already renders its own drum voice. Layering the // generated practice kit on top causes doubled hits and a white-noise hi-hat // (heard as a recurring "tsss"). Keyboard play still needs audible drums. - bool playGeneratedDrum = input.Source != DrumInputSource.Midi; - return new GameplayAudioFeedbackDecision(playGeneratedDrum, result == null); + bool playSyntheticFeedback = input.Source != DrumInputSource.Midi; + return new GameplayAudioFeedbackDecision( + playSyntheticFeedback, + playSyntheticFeedback && result == null); } public static bool ShouldPlayMiss(HitResult result) => result != null && result.Grade == HitGrade.Miss; diff --git a/src/HitTheKit.Unity/Assets/HitTheKit/Runtime/MainMenu/MainMenuController.cs b/src/HitTheKit.Unity/Assets/HitTheKit/Runtime/MainMenu/MainMenuController.cs index ddb8eb6..36e88af 100644 --- a/src/HitTheKit.Unity/Assets/HitTheKit/Runtime/MainMenu/MainMenuController.cs +++ b/src/HitTheKit.Unity/Assets/HitTheKit/Runtime/MainMenu/MainMenuController.cs @@ -4,6 +4,7 @@ using UnityEngine; using UnityEngine.SceneManagement; using UnityEngine.UIElements; +using HitTheKit.Core; using HitTheKit.Unity.Input; using HitTheKit.Unity.Gameplay; using HitTheKit.Unity.DeviceSetup; diff --git a/src/HitTheKit.Unity/Assets/HitTheKit/Tests/EditMode/DeviceSetup/DeviceSetupFoundationTests.cs b/src/HitTheKit.Unity/Assets/HitTheKit/Tests/EditMode/DeviceSetup/DeviceSetupFoundationTests.cs index 05dce2f..ecebaa4 100644 --- a/src/HitTheKit.Unity/Assets/HitTheKit/Tests/EditMode/DeviceSetup/DeviceSetupFoundationTests.cs +++ b/src/HitTheKit.Unity/Assets/HitTheKit/Tests/EditMode/DeviceSetup/DeviceSetupFoundationTests.cs @@ -128,8 +128,8 @@ public void Different_capture_creates_real_conflict_without_overwriting_candidat flow.ChoosePreset("minimal"); flow.BeginGuidedMapping(); - flow.ProcessCapturedMessage(RawMidiMessage.NoteOn(9, 37, 80)); - flow.ProcessCapturedMessage(RawMidiMessage.NoteOn(9, 37, 100)); + for (int index = 0; index < flow.Snapshot.CurrentStep.CaptureCount; index++) + flow.ProcessCapturedMessage(RawMidiMessage.NoteOn(9, 37, 80 + index)); Assert.That(flow.AcceptCurrentCapture().Succeeded, Is.True); Assert.That(flow.State, Is.EqualTo(DeviceSetupState.ConflictReview)); Assert.That(flow.Snapshot.ReviewIssues.Any(issue => diff --git a/src/HitTheKit.Unity/Assets/HitTheKit/Tests/EditMode/GameplayLearningPathTests.cs b/src/HitTheKit.Unity/Assets/HitTheKit/Tests/EditMode/GameplayLearningPathTests.cs index 54396a5..f1d8b5e 100644 --- a/src/HitTheKit.Unity/Assets/HitTheKit/Tests/EditMode/GameplayLearningPathTests.cs +++ b/src/HitTheKit.Unity/Assets/HitTheKit/Tests/EditMode/GameplayLearningPathTests.cs @@ -229,6 +229,9 @@ public void Audio_feedback_plays_drums_only_for_player_input_and_uses_a_distinct GameplayAudioFeedbackDecision midi = GameplayAudioFeedbackPolicy.ForInput( new DrumInputEvent(DrumPad.Kick, 100, 1, DrumInputSource.Midi), matchedResult); + GameplayAudioFeedbackDecision wrongMidi = GameplayAudioFeedbackPolicy.ForInput( + new DrumInputEvent(DrumPad.Snare, 100, 1, DrumInputSource.Midi), + null); Assert.That(matched.PlayDrum, Is.True); Assert.That(matched.PlayMistake, Is.False); @@ -236,6 +239,9 @@ public void Audio_feedback_plays_drums_only_for_player_input_and_uses_a_distinct Assert.That(wrong.PlayMistake, Is.True); Assert.That(midi.PlayDrum, Is.False); Assert.That(midi.PlayMistake, Is.False); + Assert.That(wrongMidi.PlayDrum, Is.False); + Assert.That(wrongMidi.PlayMistake, Is.False, + "A wrong MIDI hit must not trigger synthetic audio over the physical drum kit."); Assert.That(miss, Is.Not.Null); Assert.That(GameplayAudioFeedbackPolicy.ShouldPlayMiss(miss), Is.True); } diff --git a/src/HitTheKit.Unity/Assets/HitTheKit/Tests/EditMode/SongLibraryTests.cs b/src/HitTheKit.Unity/Assets/HitTheKit/Tests/EditMode/SongLibraryTests.cs index 2096125..c2bca0d 100644 --- a/src/HitTheKit.Unity/Assets/HitTheKit/Tests/EditMode/SongLibraryTests.cs +++ b/src/HitTheKit.Unity/Assets/HitTheKit/Tests/EditMode/SongLibraryTests.cs @@ -443,20 +443,10 @@ public void Bundled_catalog_is_rights_clean_and_contains_only_project_owned_exam Assert.That(manifest, Does.Not.Contain("://"), song.Id); Assert.That(manifest, Does.Not.Contain("/Users/"), song.Id); - if (isHighwayLearningTrack) - { - Assert.That(manifest, Does.Contain("\"bpm\": 116"), song.Id); - Assert.That(manifest, Does.Contain("\"bars\": 100"), song.Id); - Assert.That(manifest, Does.Contain("\"beatsPerBar\": 4"), song.Id); - Assert.That(manifest, Does.Contain("\"chartFile\": \"notes.json\""), song.Id); - } - else - { - Assert.That(manifest, Does.Not.Contain("\"bpm\""), song.Id); - Assert.That(manifest, Does.Not.Contain("\"bars\""), song.Id); - Assert.That(manifest, Does.Not.Contain("\"beatsPerBar\""), song.Id); - Assert.That(manifest, Does.Not.Contain("\"chartFile\""), song.Id); - } + Assert.That(manifest, Does.Not.Contain("\"bpm\""), song.Id); + Assert.That(manifest, Does.Not.Contain("\"bars\""), song.Id); + Assert.That(manifest, Does.Not.Contain("\"beatsPerBar\""), song.Id); + Assert.That(manifest, Does.Not.Contain("\"chartFile\""), song.Id); string[] commercialAssets = Directory.GetFiles(song.FolderPath) .Where(path => diff --git a/src/HitTheKit.Unity/Assets/HitTheKit/Tests/PlayMode/MainMenuPlayModeTests.cs b/src/HitTheKit.Unity/Assets/HitTheKit/Tests/PlayMode/MainMenuPlayModeTests.cs index c79f8b8..6395f4f 100644 --- a/src/HitTheKit.Unity/Assets/HitTheKit/Tests/PlayMode/MainMenuPlayModeTests.cs +++ b/src/HitTheKit.Unity/Assets/HitTheKit/Tests/PlayMode/MainMenuPlayModeTests.cs @@ -354,6 +354,7 @@ public IEnumerator Learn_and_settings_show_persisted_practice_summary_and_backup [UnityTest] public IEnumerator Learn_is_a_full_section_and_double_kick_confirms_the_selected_destination() { + PlayerPreferencesRuntime.Current.SetFirstRunCompleted(true); MainMenuController controller = null; yield return LoadMainMenu(value => controller = value); controller.SelectDestination(MainMenuDestination.Learn);