System: Add video capture feature
This commit is contained in:
@ -21,6 +21,7 @@
|
||||
#include "util/imgui_fullscreen.h"
|
||||
#include "util/imgui_manager.h"
|
||||
#include "util/input_manager.h"
|
||||
#include "util/media_capture.h"
|
||||
|
||||
#include "common/align.h"
|
||||
#include "common/error.h"
|
||||
@ -48,7 +49,9 @@ Log_SetChannel(ImGuiManager);
|
||||
|
||||
namespace ImGuiManager {
|
||||
static void FormatProcessorStat(SmallStringBase& text, double usage, double time);
|
||||
static void DrawPerformanceOverlay();
|
||||
static void DrawPerformanceOverlay(float& position_y, float scale, float margin, float spacing);
|
||||
static void DrawMediaCaptureOverlay(float& position_y, float scale, float margin, float spacing);
|
||||
static void DrawFrameTimeOverlay(float& position_y, float scale, float margin, float spacing);
|
||||
static void DrawEnhancementsOverlay();
|
||||
static void DrawInputsOverlay();
|
||||
} // namespace ImGuiManager
|
||||
@ -191,7 +194,13 @@ void ImGuiManager::RenderTextOverlays()
|
||||
const System::State state = System::GetState();
|
||||
if (state != System::State::Shutdown)
|
||||
{
|
||||
DrawPerformanceOverlay();
|
||||
const float scale = ImGuiManager::GetGlobalScale();
|
||||
const float margin = std::ceil(10.0f * scale);
|
||||
const float spacing = std::ceil(5.0f * scale);
|
||||
float position_y = margin;
|
||||
DrawPerformanceOverlay(position_y, scale, margin, spacing);
|
||||
DrawFrameTimeOverlay(position_y, scale, margin, spacing);
|
||||
DrawMediaCaptureOverlay(position_y, scale, margin, spacing);
|
||||
|
||||
if (g_settings.display_show_enhancements && state != System::State::Paused)
|
||||
DrawEnhancementsOverlay();
|
||||
@ -212,7 +221,7 @@ void ImGuiManager::FormatProcessorStat(SmallStringBase& text, double usage, doub
|
||||
text.append_format("{:.1f}% ({:.2f}ms)", usage, time);
|
||||
}
|
||||
|
||||
void ImGuiManager::DrawPerformanceOverlay()
|
||||
void ImGuiManager::DrawPerformanceOverlay(float& position_y, float scale, float margin, float spacing)
|
||||
{
|
||||
if (!(g_settings.display_show_fps || g_settings.display_show_speed || g_settings.display_show_gpu_stats ||
|
||||
g_settings.display_show_resolution || g_settings.display_show_cpu_usage ||
|
||||
@ -222,14 +231,9 @@ void ImGuiManager::DrawPerformanceOverlay()
|
||||
return;
|
||||
}
|
||||
|
||||
const float scale = ImGuiManager::GetGlobalScale();
|
||||
const float shadow_offset = std::ceil(1.0f * scale);
|
||||
const float margin = std::ceil(10.0f * scale);
|
||||
const float spacing = std::ceil(5.0f * scale);
|
||||
ImFont* fixed_font = ImGuiManager::GetFixedFont();
|
||||
ImFont* standard_font = ImGuiManager::GetStandardFont();
|
||||
float position_y = margin;
|
||||
|
||||
ImDrawList* dl = ImGui::GetBackgroundDrawList();
|
||||
SmallString text;
|
||||
ImVec2 text_size;
|
||||
@ -364,6 +368,13 @@ void ImGuiManager::DrawPerformanceOverlay()
|
||||
FormatProcessorStat(text, System::GetSWThreadUsage(), System::GetSWThreadAverageTime());
|
||||
DRAW_LINE(fixed_font, text, IM_COL32(255, 255, 255, 255));
|
||||
}
|
||||
|
||||
if (MediaCapture* cap = System::GetMediaCapture())
|
||||
{
|
||||
text.assign("CAP: ");
|
||||
FormatProcessorStat(text, cap->GetCaptureThreadUsage(), cap->GetCaptureThreadTime());
|
||||
DRAW_LINE(fixed_font, text, IM_COL32(255, 255, 255, 255));
|
||||
}
|
||||
}
|
||||
|
||||
if (g_settings.display_show_gpu_usage && g_gpu_device->IsGPUTimingEnabled())
|
||||
@ -382,67 +393,6 @@ void ImGuiManager::DrawPerformanceOverlay()
|
||||
DRAW_LINE(standard_font, text, IM_COL32(255, 255, 255, 255));
|
||||
}
|
||||
}
|
||||
|
||||
if (g_settings.display_show_frame_times)
|
||||
{
|
||||
const ImVec2 history_size(200.0f * scale, 50.0f * scale);
|
||||
ImGui::SetNextWindowSize(ImVec2(history_size.x, history_size.y));
|
||||
ImGui::SetNextWindowPos(ImVec2(ImGui::GetIO().DisplaySize.x - margin - history_size.x, position_y));
|
||||
ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0.0f, 0.0f, 0.0f, 0.25f));
|
||||
ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(0.0f, 0.0f, 0.0f, 0.0f));
|
||||
ImGui::PushStyleColor(ImGuiCol_PlotLines, ImVec4(1.0f, 1.0f, 1.0f, 1.0f));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0.0f, 0.0f));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 0.0f);
|
||||
if (ImGui::Begin("##frame_times", nullptr, ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoInputs))
|
||||
{
|
||||
ImGui::PushFont(fixed_font);
|
||||
|
||||
auto [min, max] = GetMinMax(System::GetFrameTimeHistory());
|
||||
|
||||
// add a little bit of space either side, so we're not constantly resizing
|
||||
if ((max - min) < 4.0f)
|
||||
{
|
||||
min = min - std::fmod(min, 1.0f);
|
||||
max = max - std::fmod(max, 1.0f) + 1.0f;
|
||||
min = std::max(min - 2.0f, 0.0f);
|
||||
max += 2.0f;
|
||||
}
|
||||
|
||||
ImGui::PlotEx(
|
||||
ImGuiPlotType_Lines, "##frame_times",
|
||||
[](void*, int idx) -> float {
|
||||
return System::GetFrameTimeHistory()[((System::GetFrameTimeHistoryPos() + idx) %
|
||||
System::NUM_FRAME_TIME_SAMPLES)];
|
||||
},
|
||||
nullptr, System::NUM_FRAME_TIME_SAMPLES, 0, nullptr, min, max, history_size);
|
||||
|
||||
ImDrawList* win_dl = ImGui::GetCurrentWindow()->DrawList;
|
||||
const ImVec2 wpos(ImGui::GetCurrentWindow()->Pos);
|
||||
|
||||
text.format("{:.1f} ms", max);
|
||||
text_size = fixed_font->CalcTextSizeA(fixed_font->FontSize, FLT_MAX, 0.0f, text.c_str(), text.end_ptr());
|
||||
win_dl->AddText(ImVec2(wpos.x + history_size.x - text_size.x - spacing + shadow_offset, wpos.y + shadow_offset),
|
||||
IM_COL32(0, 0, 0, 100), text.c_str(), text.end_ptr());
|
||||
win_dl->AddText(ImVec2(wpos.x + history_size.x - text_size.x - spacing, wpos.y), IM_COL32(255, 255, 255, 255),
|
||||
text.c_str(), text.end_ptr());
|
||||
|
||||
text.format("{:.1f} ms", min);
|
||||
text_size = fixed_font->CalcTextSizeA(fixed_font->FontSize, FLT_MAX, 0.0f, text.c_str(), text.end_ptr());
|
||||
win_dl->AddText(ImVec2(wpos.x + history_size.x - text_size.x - spacing + shadow_offset,
|
||||
wpos.y + history_size.y - fixed_font->FontSize + shadow_offset),
|
||||
IM_COL32(0, 0, 0, 100), text.c_str(), text.end_ptr());
|
||||
win_dl->AddText(
|
||||
ImVec2(wpos.x + history_size.x - text_size.x - spacing, wpos.y + history_size.y - fixed_font->FontSize),
|
||||
IM_COL32(255, 255, 255, 255), text.c_str(), text.end_ptr());
|
||||
ImGui::PopFont();
|
||||
}
|
||||
ImGui::End();
|
||||
ImGui::PopStyleVar(5);
|
||||
ImGui::PopStyleColor(3);
|
||||
}
|
||||
}
|
||||
else if (g_settings.display_show_status_indicators && state == System::State::Paused &&
|
||||
!FullscreenUI::HasActiveWindow())
|
||||
@ -547,6 +497,114 @@ void ImGuiManager::DrawEnhancementsOverlay()
|
||||
IM_COL32(255, 255, 255, 255), text.c_str(), text.end_ptr());
|
||||
}
|
||||
|
||||
void ImGuiManager::DrawMediaCaptureOverlay(float& position_y, float scale, float margin, float spacing)
|
||||
{
|
||||
MediaCapture* const cap = System::GetMediaCapture();
|
||||
if (!cap || FullscreenUI::HasActiveWindow())
|
||||
return;
|
||||
|
||||
const float shadow_offset = std::ceil(scale);
|
||||
ImFont* const standard_font = ImGuiManager::GetStandardFont();
|
||||
ImDrawList* dl = ImGui::GetBackgroundDrawList();
|
||||
|
||||
static constexpr const char* ICON = ICON_FA_VIDEO;
|
||||
const time_t elapsed_time = cap->GetElapsedTime();
|
||||
const TinyString text_msg = TinyString::from_format(" {:02d}:{:02d}:{:02d}", elapsed_time / 3600,
|
||||
(elapsed_time % 3600) / 60, (elapsed_time % 3600) % 60);
|
||||
const ImVec2 icon_size = standard_font->CalcTextSizeA(standard_font->FontSize, std::numeric_limits<float>::max(),
|
||||
-1.0f, ICON, nullptr, nullptr);
|
||||
const ImVec2 text_size = standard_font->CalcTextSizeA(standard_font->FontSize, std::numeric_limits<float>::max(),
|
||||
-1.0f, text_msg.c_str(), text_msg.end_ptr(), nullptr);
|
||||
|
||||
const float box_margin = 2.0f * scale;
|
||||
const ImVec2 box_size = ImVec2(icon_size.x + shadow_offset + text_size.x + box_margin * 2.0f,
|
||||
std::max(icon_size.x, text_size.y) + box_margin * 2.0f);
|
||||
const ImVec2 box_pos = ImVec2(ImGui::GetIO().DisplaySize.x - margin - box_size.x, position_y);
|
||||
dl->AddRectFilled(box_pos, box_pos + box_size, IM_COL32(0, 0, 0, 64), box_margin);
|
||||
|
||||
const ImVec2 text_start = ImVec2(box_pos.x + box_margin, box_pos.y + box_margin);
|
||||
dl->AddText(standard_font, standard_font->FontSize,
|
||||
ImVec2(text_start.x + shadow_offset, text_start.y + shadow_offset), IM_COL32(0, 0, 0, 100), ICON);
|
||||
dl->AddText(standard_font, standard_font->FontSize,
|
||||
ImVec2(text_start.x + icon_size.x + shadow_offset, text_start.y + shadow_offset), IM_COL32(0, 0, 0, 100),
|
||||
text_msg.c_str(), text_msg.end_ptr());
|
||||
dl->AddText(standard_font, standard_font->FontSize, text_start, IM_COL32(255, 0, 0, 255), ICON);
|
||||
dl->AddText(standard_font, standard_font->FontSize, ImVec2(text_start.x + icon_size.x, text_start.y),
|
||||
IM_COL32(255, 255, 255, 255), text_msg.c_str(), text_msg.end_ptr());
|
||||
|
||||
position_y += box_size.y + spacing;
|
||||
}
|
||||
|
||||
void ImGuiManager::DrawFrameTimeOverlay(float& position_y, float scale, float margin, float spacing)
|
||||
{
|
||||
if (!g_settings.display_show_frame_times || System::IsPaused())
|
||||
return;
|
||||
|
||||
const float shadow_offset = std::ceil(1.0f * scale);
|
||||
ImFont* fixed_font = ImGuiManager::GetFixedFont();
|
||||
|
||||
const ImVec2 history_size(200.0f * scale, 50.0f * scale);
|
||||
ImGui::SetNextWindowSize(ImVec2(history_size.x, history_size.y));
|
||||
ImGui::SetNextWindowPos(ImVec2(ImGui::GetIO().DisplaySize.x - margin - history_size.x, position_y));
|
||||
ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0.0f, 0.0f, 0.0f, 0.25f));
|
||||
ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(0.0f, 0.0f, 0.0f, 0.0f));
|
||||
ImGui::PushStyleColor(ImGuiCol_PlotLines, ImVec4(1.0f, 1.0f, 1.0f, 1.0f));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0.0f, 0.0f));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 0.0f);
|
||||
if (ImGui::Begin("##frame_times", nullptr, ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoInputs))
|
||||
{
|
||||
ImGui::PushFont(fixed_font);
|
||||
|
||||
auto [min, max] = GetMinMax(System::GetFrameTimeHistory());
|
||||
|
||||
// add a little bit of space either side, so we're not constantly resizing
|
||||
if ((max - min) < 4.0f)
|
||||
{
|
||||
min = min - std::fmod(min, 1.0f);
|
||||
max = max - std::fmod(max, 1.0f) + 1.0f;
|
||||
min = std::max(min - 2.0f, 0.0f);
|
||||
max += 2.0f;
|
||||
}
|
||||
|
||||
ImGui::PlotEx(
|
||||
ImGuiPlotType_Lines, "##frame_times",
|
||||
[](void*, int idx) -> float {
|
||||
return System::GetFrameTimeHistory()[((System::GetFrameTimeHistoryPos() + idx) %
|
||||
System::NUM_FRAME_TIME_SAMPLES)];
|
||||
},
|
||||
nullptr, System::NUM_FRAME_TIME_SAMPLES, 0, nullptr, min, max, history_size);
|
||||
|
||||
ImDrawList* win_dl = ImGui::GetCurrentWindow()->DrawList;
|
||||
const ImVec2 wpos(ImGui::GetCurrentWindow()->Pos);
|
||||
|
||||
TinyString text;
|
||||
text.format("{:.1f} ms", max);
|
||||
ImVec2 text_size = fixed_font->CalcTextSizeA(fixed_font->FontSize, FLT_MAX, 0.0f, text.c_str(), text.end_ptr());
|
||||
win_dl->AddText(ImVec2(wpos.x + history_size.x - text_size.x - spacing + shadow_offset, wpos.y + shadow_offset),
|
||||
IM_COL32(0, 0, 0, 100), text.c_str(), text.end_ptr());
|
||||
win_dl->AddText(ImVec2(wpos.x + history_size.x - text_size.x - spacing, wpos.y), IM_COL32(255, 255, 255, 255),
|
||||
text.c_str(), text.end_ptr());
|
||||
|
||||
text.format("{:.1f} ms", min);
|
||||
text_size = fixed_font->CalcTextSizeA(fixed_font->FontSize, FLT_MAX, 0.0f, text.c_str(), text.end_ptr());
|
||||
win_dl->AddText(ImVec2(wpos.x + history_size.x - text_size.x - spacing + shadow_offset,
|
||||
wpos.y + history_size.y - fixed_font->FontSize + shadow_offset),
|
||||
IM_COL32(0, 0, 0, 100), text.c_str(), text.end_ptr());
|
||||
win_dl->AddText(
|
||||
ImVec2(wpos.x + history_size.x - text_size.x - spacing, wpos.y + history_size.y - fixed_font->FontSize),
|
||||
IM_COL32(255, 255, 255, 255), text.c_str(), text.end_ptr());
|
||||
ImGui::PopFont();
|
||||
}
|
||||
ImGui::End();
|
||||
ImGui::PopStyleVar(5);
|
||||
ImGui::PopStyleColor(3);
|
||||
|
||||
position_y += history_size.y + spacing;
|
||||
}
|
||||
|
||||
void ImGuiManager::DrawInputsOverlay()
|
||||
{
|
||||
const float scale = ImGuiManager::GetGlobalScale();
|
||||
|
||||
Reference in New Issue
Block a user