From 81e85d6952ec2f510eee6403fc555c59d532ae42 Mon Sep 17 00:00:00 2001 From: Jimin Park Date: Wed, 12 Jan 2022 12:02:55 +0900 Subject: [PATCH 1/3] Attempt to fix #549 Currently the cause is unknown but it may be possible that m_currObject was incorrectly set. --- Beatmap/src/BeatmapPlayback.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Beatmap/src/BeatmapPlayback.cpp b/Beatmap/src/BeatmapPlayback.cpp index ebcc529d2..0b6442f9a 100644 --- a/Beatmap/src/BeatmapPlayback.cpp +++ b/Beatmap/src/BeatmapPlayback.cpp @@ -22,12 +22,11 @@ bool BeatmapPlayback::Reset(MapTime initTime, MapTime start) m_playRange = { start, start }; m_currObject = m_beatmap->GetFirstObjectState(); - m_currObject = m_SelectHitObject(std::max(initTime, start), true); m_currLaserObject = m_currObject; m_currAlertObject = m_currObject; - m_currentTiming = m_beatmap->GetTimingPoint(initTime); + m_currentTiming = m_beatmap->GetFirstTimingPoint(); m_currentLaneTogglePoint = m_beatmap->GetFirstLaneTogglePoint(); m_currentTrackRollBehaviour = TrackRollBehaviour::Normal; From fdf39562080c3b29a32cb3b64e9691e226b68cdc Mon Sep 17 00:00:00 2001 From: Jimin Park Date: Sat, 15 Jan 2022 01:57:26 +0900 Subject: [PATCH 2/3] Added more detailed infor on debug HUD --- Beatmap/include/Beatmap/BeatmapPlayback.hpp | 3 + Beatmap/src/BeatmapPlayback.cpp | 86 +++++++++++- Main/src/Game.cpp | 137 ++++++++++++++------ 3 files changed, 183 insertions(+), 43 deletions(-) diff --git a/Beatmap/include/Beatmap/BeatmapPlayback.hpp b/Beatmap/include/Beatmap/BeatmapPlayback.hpp index 5f860fca6..5bbd62ba5 100644 --- a/Beatmap/include/Beatmap/BeatmapPlayback.hpp +++ b/Beatmap/include/Beatmap/BeatmapPlayback.hpp @@ -125,6 +125,9 @@ class BeatmapPlayback Delegate OnEventChanged; + /// Used for debugging + Vector GetStateString() const; + private: // Selects an object or timing point based on a given input state // if allowReset is true the search starts from the start of the object list if current point lies beyond given input time diff --git a/Beatmap/src/BeatmapPlayback.cpp b/Beatmap/src/BeatmapPlayback.cpp index 0b6442f9a..112f132e9 100644 --- a/Beatmap/src/BeatmapPlayback.cpp +++ b/Beatmap/src/BeatmapPlayback.cpp @@ -622,4 +622,88 @@ bool BeatmapPlayback::IsEndTiming(const Beatmap::TimingPointsIterator& obj) cons bool BeatmapPlayback::IsEndLaneToggle(const Beatmap::LaneTogglePointsIterator& obj) const { return obj == m_beatmap->GetEndLaneTogglePoint(); -} \ No newline at end of file +} + +Vector BeatmapPlayback::GetStateString() const +{ + auto ObjectStateToStr = [](const ObjectState* state) + { + if (state == nullptr) + { + return String{"null"}; + } + + const auto* obj = (const MultiObjectState*) state; + + switch (obj->type) + { + case ObjectType::Single: + { + const auto* state = (const ButtonObjectState*)obj; + return Utility::Sprintf("%d(type=single index=%u)", obj->time, static_cast(state->index)); + } + break; + case ObjectType::Hold: + { + const auto* state = (const HoldObjectState*)obj; + return Utility::Sprintf("%d(type=hold index=%u len=%d)", obj->time, static_cast(state->index), state->duration); + } + break; + case ObjectType::Laser: + { + const auto* state = (const LaserObjectState*)obj; + return Utility::Sprintf("%d(type=laser %s len=%d start=%.3f end=%.3f flags=%x)", + obj->time, state->index == 0 ? "left" : state->index == 1 ? "right" : "invalid", state->duration, state->points[0], state->points[1], static_cast(state->flags)); + } + break; + case ObjectType::Event: + { + const auto* state = (const EventObjectState*)obj; + return Utility::Sprintf("%d(type=event key=%d)", + obj->time, static_cast(state->key)); + } + break; + default: + return Utility::Sprintf("%d(type=%u)", obj->time, static_cast(obj->type)); + } + }; + + auto BeatmapObjectToStr = [&](const Beatmap::ObjectsIterator& it) + { + if (IsEndObject(it)) + { + return String{"end"}; + } + + return ObjectStateToStr(it->get()); + }; + + Vector lines; + + const auto& tp = GetCurrentTimingPoint(); + const float currentBPM = (float)(60000.0 / tp.beatDuration); + lines.Add(Utility::Sprintf("TimingPoint: time=%d bpm=%.3f sig=%d/%d", tp.time, currentBPM, tp.numerator, tp.denominator)); + + lines.Add(Utility::Sprintf( + "PlayRange: %d to %d | Playback: time=%d", + m_playRange.begin, m_playRange.end, m_playbackTime + )); + + lines.Add(Utility::Sprintf("CurrObject: %s", BeatmapObjectToStr(m_currObject))); + lines.Add(Utility::Sprintf("CurrLaser: %s", BeatmapObjectToStr(m_currLaserObject))); + lines.Add(Utility::Sprintf("CurrAlert: %s", BeatmapObjectToStr(m_currAlertObject))); + + if (m_objectsByTime.empty()) + { + lines.Add("Objects: none"); + } + else + { + const auto* firstObj = m_objectsByTime.begin()->second; + const auto* lastObj = m_objectsByTime.rbegin()->second; + + lines.Add(Utility::Sprintf("Objects: %u objects, %s to %s", m_objectsByTime.size(), ObjectStateToStr(firstObj), ObjectStateToStr(lastObj))); + } + + return lines; +} diff --git a/Main/src/Game.cpp b/Main/src/Game.cpp index 959bc7f1d..1bb27249d 100755 --- a/Main/src/Game.cpp +++ b/Main/src/Game.cpp @@ -1804,65 +1804,118 @@ class Game_Impl : public Game return Vector2(0, 12); }; - //Vector2 canvasRes = GUISlotBase::ApplyFill(FillMode::Fit, Vector2(640, 480), Rect(0, 0, g_resolution.x, g_resolution.y)).size; - //Vector2 topLeft = Vector2(g_resolution / 2 - canvasRes / 2); - //Vector2 bottomRight = topLeft + canvasRes; - //topLeft.y = Math::Min(topLeft.y, g_resolution.y * 0.2f); - - const BeatmapSettings& bms = m_beatmap->GetMapSettings(); const TimingPoint& tp = m_playback.GetCurrentTimingPoint(); - //Vector2 textPos = topLeft + Vector2i(5, 0); + Vector2 textPos = Vector2i(5, 0); - textPos.y += RenderText(bms.title, textPos).y; - textPos.y += RenderText(bms.artist, textPos).y; - textPos.y += RenderText(Utility::Sprintf("%.2f FPS", g_application->GetRenderFPS()), textPos).y; - textPos.y += RenderText(Utility::Sprintf("Offset (ms): Global %d, Song %d, Audio %d (%d)", - m_globalOffset, m_songOffset, GetAudioOffset(), g_audio->audioLatency), textPos).y; - - float currentBPM = (float)(60000.0 / tp.beatDuration); - textPos.y += RenderText(Utility::Sprintf("BPM: %.1f | Time Sig: %d/%d", currentBPM, tp.numerator, tp.denominator), textPos).y; - textPos.y += RenderText(Utility::Sprintf("Hit Window: p=%d g=%d h=%d s=%d m=%d", - m_scoring.hitWindow.perfect, m_scoring.hitWindow.good, m_scoring.hitWindow.hold, m_scoring.hitWindow.slam, m_scoring.hitWindow.miss), textPos).y; - textPos.y += RenderText(Utility::Sprintf("Paused: %s, LastMapTime: %d", m_paused ? "Yes" : "No", m_lastMapTime), textPos).y; - if (IsPartialPlay()) - textPos.y += RenderText(Utility::Sprintf("Partial play: from %d ms to %d ms", m_playOptions.range.begin, m_playOptions.range.end), textPos).y; - textPos.y += RenderText(Utility::Sprintf("Laser Filter Input: %f", m_scoring.GetLaserOutput()), textPos).y; - - textPos.y += RenderText(Utility::Sprintf("Score: %d/%d (Max: %d)", m_scoring.currentHitScore, m_scoring.currentMaxScore, m_scoring.mapTotals.maxScore), textPos).y; - textPos.y += RenderText(Utility::Sprintf("Actual Score: %d", m_scoring.CalculateCurrentScore()), textPos).y; - Gauge* gauge = m_scoring.GetTopGauge(); - if (gauge) + // Chart info { - textPos.y += RenderText(Utility::Sprintf("Health Gauge: %s, %f", gauge->GetName(), gauge->GetValue()), textPos).y; + if (m_chartIndex) + { + textPos.y += RenderText(Utility::Sprintf("ChartHash: %s", m_chartIndex->hash), textPos, Color::White).y; + textPos.y += RenderText(Utility::Sprintf( + "ChartIndex: title=\"%s\" diff=\"%s\" lv=%d a=\"%s\" e=\"%s\"", + m_chartIndex->title, m_chartIndex->diff_name, m_chartIndex->level, m_chartIndex->artist, m_chartIndex->effector + ), textPos, Color::White).y; + } + + const BeatmapSettings& bms = m_beatmap->GetMapSettings(); + textPos.y += RenderText(Utility::Sprintf( + "Beatmap: title=\"%s\" diff=%hhd lv=%d a=\"%s\" e=\"%s\"", + bms.title, bms.difficulty, bms.level, bms.artist, bms.effector + ), textPos, Color::White).y; } - textPos.y += RenderText(Utility::Sprintf("Roll: %f(x%f) %s", - m_camera.GetRoll(), m_rollIntensity, m_camera.GetRollKeep() ? "[Keep]" : ""), textPos).y; + // Playback info + { + textPos.y += RenderText(Utility::Sprintf( + "Offset (ms): global=%d song=%d temp=%d | audio=%d (latency=%d)", + m_globalOffset, m_songOffset, m_tempOffset, GetAudioOffset(), g_audio->audioLatency + ), textPos, Color::Yellow).y; - textPos.y += RenderText(Utility::Sprintf("Track Zoom Top: %f", m_camera.pLanePitch), textPos).y; - textPos.y += RenderText(Utility::Sprintf("Track Zoom Bottom: %f", m_camera.pLaneZoom), textPos).y; - textPos.y += RenderText(Utility::Sprintf("Scroll Speed: %f", m_playback.GetScrollSpeed()), textPos).y; + textPos.y += RenderText(Utility::Sprintf("Paused: %s, LastMapTime: %d", m_paused ? "Yes" : "No", m_lastMapTime), textPos, Color::Yellow).y; - Vector2 buttonStateTextPos = Vector2(g_resolution.x - 200.0f, 100.0f); - RenderText(g_input.GetControllerStateString(), buttonStateTextPos); + for (const String& line : m_playback.GetStateString()) + { + textPos.y += RenderText(line, textPos, Color::Cyan).y; + } - if (!IsStorableScore()) - { - if (m_isPracticeSetup) + const float viewRange = m_track ? m_track->GetViewRange() : -1.0f; + textPos.y += RenderText(Utility::Sprintf("SpeedMod: hi=%.3f mod=%.3f | ViewRange: %.4f", m_hispeed, m_modSpeed, viewRange), textPos, Color::Yellow).y; + + if (IsPartialPlay()) { - textPos.y += RenderText("Practice setup", textPos, Color::Magenta).y; + textPos.y += RenderText(Utility::Sprintf("Partial play: from %d ms to %d ms", m_playOptions.range.begin, m_playOptions.range.end), textPos, Color::Magenta).y; } - else if(m_scoring.autoplayInfo.autoplay) + + textPos.y += RenderText(Utility::Sprintf( + "Playback speeed: %.3f (option set to %.3f)", GetPlaybackSpeed(), m_playOptions.playbackSpeed + ), textPos, m_playOptions.playbackSpeed < 1.0f ? Color::Magenta : Color::Yellow).y; + } + + // Input and scoring info + { + if (!IsStorableScore()) { - textPos.y += RenderText("Autoplay enabled", textPos, Color::Magenta).y; + String notStorableReason = "Other"; + + if (m_isPracticeSetup) + { + notStorableReason = "PracticeSetup"; + } + else if (m_scoring.autoplayInfo.IsAutoplayButtons()) + { + notStorableReason = "Autoplay("; + + if (m_scoring.autoplayInfo.autoplay) + { + notStorableReason += "autoplay,"; + } + + if (m_scoring.autoplayInfo.autoplayButtons) + { + notStorableReason += "buttons,"; + } + + notStorableReason += ")"; + } + + textPos.y += RenderText(Utility::Sprintf("Score not storable: %s", notStorableReason), textPos, Color::Magenta).y; } - else + + textPos.y += RenderText(Utility::Sprintf( + "Hit Window: p=%d g=%d h=%d s=%d m=%d", + m_scoring.hitWindow.perfect, m_scoring.hitWindow.good, m_scoring.hitWindow.hold, m_scoring.hitWindow.slam, m_scoring.hitWindow.miss + ), textPos, m_scoring.hitWindow <= HitWindow::NORMAL ? Color{1.0f, 1.0f, 0.5f, 1.0f} : Color::Magenta).y; + + textPos.y += RenderText(Utility::Sprintf("Laser Filter Input: %f", m_scoring.GetLaserOutput()), textPos).y; + + textPos.y += RenderText(Utility::Sprintf( + "Score: %d/%d (Max: %d) = %d", + m_scoring.currentHitScore, m_scoring.currentMaxScore, m_scoring.mapTotals.maxScore, m_scoring.CalculateCurrentScore() + ), textPos).y; + + + if (const Gauge* gauge = m_scoring.GetTopGauge()) { - textPos.y += RenderText("Score not storable", textPos, Color::Magenta).y; + textPos.y += RenderText(Utility::Sprintf("Health Gauge: %s, %f", gauge->GetName(), gauge->GetValue()), textPos).y; } } + // Camera and rendering info + { + textPos.y += RenderText(Utility::Sprintf("Roll: %f(x%f) %s", + m_camera.GetRoll(), m_rollIntensity, m_camera.GetRollKeep() ? "[Keep]" : ""), textPos).y; + + textPos.y += RenderText(Utility::Sprintf("Track Zoom: top=%.6f bottom=%.6f side=%.6f", m_camera.pLanePitch, m_camera.pLaneZoom, m_camera.pLaneOffset), textPos).y; + textPos.y += RenderText(Utility::Sprintf("Scroll Speed: %f", m_playback.GetScrollSpeed()), textPos).y; + + textPos.y += RenderText(Utility::Sprintf("%.2f FPS", g_application->GetRenderFPS()), textPos).y; + } + + Vector2 buttonStateTextPos = Vector2(g_resolution.x - 200.0f, 100.0f); + RenderText(g_input.GetControllerStateString(), buttonStateTextPos); + uint32 hitsShown = 0; // Show all hit debug info on screen (up to a maximum) for(auto it = m_scoring.hitStats.rbegin(); it != m_scoring.hitStats.rend(); it++) From a20906bc35898bdcbc1f2ba2c9ff6e0c9900d4ad Mon Sep 17 00:00:00 2001 From: Jimin Park Date: Sat, 15 Jan 2022 18:50:36 +0900 Subject: [PATCH 3/3] Tweaked some debug HUD texts and added sud/hid info --- Main/src/Game.cpp | 60 +++++++++++++++++++++++++++++------------------ 1 file changed, 37 insertions(+), 23 deletions(-) diff --git a/Main/src/Game.cpp b/Main/src/Game.cpp index 1bb27249d..992ba8930 100755 --- a/Main/src/Game.cpp +++ b/Main/src/Game.cpp @@ -1812,45 +1812,43 @@ class Game_Impl : public Game { if (m_chartIndex) { - textPos.y += RenderText(Utility::Sprintf("ChartHash: %s", m_chartIndex->hash), textPos, Color::White).y; + textPos.y += RenderText(Utility::Sprintf("ChartHash: %s", m_chartIndex->hash), textPos, Color::Cyan).y; textPos.y += RenderText(Utility::Sprintf( "ChartIndex: title=\"%s\" diff=\"%s\" lv=%d a=\"%s\" e=\"%s\"", m_chartIndex->title, m_chartIndex->diff_name, m_chartIndex->level, m_chartIndex->artist, m_chartIndex->effector - ), textPos, Color::White).y; + ), textPos, Color::Cyan).y; } const BeatmapSettings& bms = m_beatmap->GetMapSettings(); textPos.y += RenderText(Utility::Sprintf( "Beatmap: title=\"%s\" diff=%hhd lv=%d a=\"%s\" e=\"%s\"", bms.title, bms.difficulty, bms.level, bms.artist, bms.effector - ), textPos, Color::White).y; + ), textPos, Color::Cyan).y; } // Playback info { - textPos.y += RenderText(Utility::Sprintf( - "Offset (ms): global=%d song=%d temp=%d | audio=%d (latency=%d)", - m_globalOffset, m_songOffset, m_tempOffset, GetAudioOffset(), g_audio->audioLatency - ), textPos, Color::Yellow).y; - - textPos.y += RenderText(Utility::Sprintf("Paused: %s, LastMapTime: %d", m_paused ? "Yes" : "No", m_lastMapTime), textPos, Color::Yellow).y; - - for (const String& line : m_playback.GetStateString()) - { - textPos.y += RenderText(line, textPos, Color::Cyan).y; - } - - const float viewRange = m_track ? m_track->GetViewRange() : -1.0f; - textPos.y += RenderText(Utility::Sprintf("SpeedMod: hi=%.3f mod=%.3f | ViewRange: %.4f", m_hispeed, m_modSpeed, viewRange), textPos, Color::Yellow).y; - if (IsPartialPlay()) { - textPos.y += RenderText(Utility::Sprintf("Partial play: from %d ms to %d ms", m_playOptions.range.begin, m_playOptions.range.end), textPos, Color::Magenta).y; + textPos.y += RenderText(Utility::Sprintf("Partial play: from %d ms to %d ms", m_playOptions.range.begin, m_playOptions.range.end), textPos, Color::Red).y; } textPos.y += RenderText(Utility::Sprintf( "Playback speeed: %.3f (option set to %.3f)", GetPlaybackSpeed(), m_playOptions.playbackSpeed - ), textPos, m_playOptions.playbackSpeed < 1.0f ? Color::Magenta : Color::Yellow).y; + ), textPos, m_playOptions.playbackSpeed < 1.0f ? Color::Red : Color::Yellow).y; + + textPos.y += RenderText(Utility::Sprintf( + "Offset (ms): global=%d song=%d temp=%d | audio=%d (latency=%d)", + m_globalOffset, m_songOffset, m_tempOffset, GetAudioOffset(), g_audio->audioLatency + ), textPos, Color::Green).y; + + textPos.y += RenderText(Utility::Sprintf("Paused: %s, LastMapTime: %d", m_paused ? "Yes" : "No", m_lastMapTime), textPos, Color::Green).y; + } + + // Playback details + for (const String& line : m_playback.GetStateString()) + { + textPos.y += RenderText(line, textPos, Color::White).y; } // Input and scoring info @@ -1879,14 +1877,18 @@ class Game_Impl : public Game notStorableReason += ")"; } + else if (IsPartialPlay()) + { + notStorableReason += "PartialPlay"; + } - textPos.y += RenderText(Utility::Sprintf("Score not storable: %s", notStorableReason), textPos, Color::Magenta).y; + textPos.y += RenderText(Utility::Sprintf("Score not storable: %s", notStorableReason), textPos, Color::Red).y; } textPos.y += RenderText(Utility::Sprintf( - "Hit Window: p=%d g=%d h=%d s=%d m=%d", + "Hit Window (ms): p=%d g=%d h=%d s=%d m=%d", m_scoring.hitWindow.perfect, m_scoring.hitWindow.good, m_scoring.hitWindow.hold, m_scoring.hitWindow.slam, m_scoring.hitWindow.miss - ), textPos, m_scoring.hitWindow <= HitWindow::NORMAL ? Color{1.0f, 1.0f, 0.5f, 1.0f} : Color::Magenta).y; + ), textPos, m_scoring.hitWindow <= HitWindow::NORMAL ? Color{1.0f, 1.0f, 0.5f, 1.0f} : Color::Red).y; textPos.y += RenderText(Utility::Sprintf("Laser Filter Input: %f", m_scoring.GetLaserOutput()), textPos).y; @@ -1904,6 +1906,18 @@ class Game_Impl : public Game // Camera and rendering info { + const float viewRange = m_track ? m_track->GetViewRange() : -1.0f; + textPos.y += RenderText(Utility::Sprintf("SpeedMod: hi=%.3f mod=%.3f | ViewRange: %.4f", m_hispeed, m_modSpeed, viewRange), textPos).y; + + if (m_track) + { + textPos.y += RenderText(Utility::Sprintf( + "HidSud: hid=%.4f hidFade=%.4f sud=%.4f sudFade=%.4f", + m_track->hiddenCutoff, m_track->hiddenFadewindow, + m_track->suddenCutoff, m_track->suddenFadewindow + ), textPos).y; + } + textPos.y += RenderText(Utility::Sprintf("Roll: %f(x%f) %s", m_camera.GetRoll(), m_rollIntensity, m_camera.GetRollKeep() ? "[Keep]" : ""), textPos).y;