Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added more informations on debug HUD (for investigating #549) #551

Merged
merged 3 commits into from
Jan 15, 2022
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
3 changes: 3 additions & 0 deletions Beatmap/include/Beatmap/BeatmapPlayback.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,9 @@ class BeatmapPlayback

Delegate<EventKey, EventData> OnEventChanged;

/// Used for debugging
Vector<String> 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
Expand Down
89 changes: 86 additions & 3 deletions Beatmap/src/BeatmapPlayback.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -623,4 +622,88 @@ bool BeatmapPlayback::IsEndTiming(const Beatmap::TimingPointsIterator& obj) cons
bool BeatmapPlayback::IsEndLaneToggle(const Beatmap::LaneTogglePointsIterator& obj) const
{
return obj == m_beatmap->GetEndLaneTogglePoint();
}
}

Vector<String> 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<unsigned int>(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<unsigned int>(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<unsigned int>(state->flags));
}
break;
case ObjectType::Event:
{
const auto* state = (const EventObjectState*)obj;
return Utility::Sprintf("%d(type=event key=%d)",
obj->time, static_cast<int>(state->key));
}
break;
default:
return Utility::Sprintf("%d(type=%u)", obj->time, static_cast<unsigned int>(obj->type));
}
};

auto BeatmapObjectToStr = [&](const Beatmap::ObjectsIterator& it)
{
if (IsEndObject(it))
{
return String{"end"};
}

return ObjectStateToStr(it->get());
};

Vector<String> 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;
}
149 changes: 108 additions & 41 deletions Main/src/Game.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1804,65 +1804,132 @@ 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::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::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::Cyan).y;
}

textPos.y += RenderText(Utility::Sprintf("Roll: %f(x%f) %s",
m_camera.GetRoll(), m_rollIntensity, m_camera.GetRollKeep() ? "[Keep]" : ""), textPos).y;
// Playback info
{
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::Red).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(
"Playback speeed: %.3f (option set to %.3f)", GetPlaybackSpeed(), m_playOptions.playbackSpeed
), textPos, m_playOptions.playbackSpeed < 1.0f ? Color::Red : Color::Yellow).y;

Vector2 buttonStateTextPos = Vector2(g_resolution.x - 200.0f, 100.0f);
RenderText(g_input.GetControllerStateString(), buttonStateTextPos);
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;

if (!IsStorableScore())
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
{
if (m_isPracticeSetup)
if (!IsStorableScore())
{
textPos.y += RenderText("Practice setup", 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 += ")";
}
else if (IsPartialPlay())
{
notStorableReason += "PartialPlay";
}

textPos.y += RenderText(Utility::Sprintf("Score not storable: %s", notStorableReason), textPos, Color::Red).y;
}
else if(m_scoring.autoplayInfo.autoplay)

textPos.y += RenderText(Utility::Sprintf(
"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::Red).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("Autoplay enabled", textPos, Color::Magenta).y;
textPos.y += RenderText(Utility::Sprintf("Health Gauge: %s, %f", gauge->GetName(), gauge->GetValue()), textPos).y;
}
else
}

// 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("Score not storable", textPos, Color::Magenta).y;
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;

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++)
Expand Down