#pragma once #include #include #include namespace onion::overlay { inline constexpr float kOffscreen = -4096.0f; inline constexpr float kFontH = 18.0f; inline constexpr float kBarExtra = 6.0f; inline constexpr float kTextTopInset = 5.0f; inline constexpr float kGap = 28.0f; inline constexpr float kEdgeInset = 24.0f; inline constexpr float kCpuAvgWidth = 190.0f; inline constexpr float kCpuAllWidth = 420.0f; inline constexpr float kGpuWidth = 190.0f; inline constexpr float kRamWidth = 170.0f; inline constexpr float kIpWidth = 200.0f; inline constexpr float kFanWidth = 130.0f; inline constexpr float kFpsWidth = 130.0f; inline constexpr int kMetricCount = 6; inline constexpr int kMetricFps = 0; inline constexpr int kMetricCpu = 1; inline constexpr int kMetricGpu = 2; inline constexpr int kMetricMemory = 3; inline constexpr int kMetricIp = 4; inline constexpr int kMetricFan = 5; enum class BarEdge { Top, Bottom }; enum class BarAlign { Left, Center, Right }; inline BarEdge bar_edge_from_pos(int pos) { return (pos == 2 || pos == 3) ? BarEdge::Bottom : BarEdge::Top; } inline BarAlign bar_align_from_value(int align) { if (align == 0) { return BarAlign::Left; } if (align == 2) { return BarAlign::Right; } return BarAlign::Center; } inline float pack_origin(float screen_w, float content_w, BarAlign align) { if (content_w <= 0.0f) { return kOffscreen; } if (align == BarAlign::Right) { const float x = screen_w - kEdgeInset - content_w; return x < kEdgeInset ? kEdgeInset : x; } if (align == BarAlign::Left) { return kEdgeInset; } return (screen_w - content_w) * 0.5f; } struct Layout { float screen_w = 0.0f; float screen_h = 0.0f; float bar_x = 0.0f; float bar_y = 0.0f; float bar_w = 0.0f; float bar_h = kFontH + kBarExtra; float label_margin_top = kTextTopInset; float overlay_cpu_x = 160.0f; float overlay_cpu_y = 12.0f; float overlay_gpu_x = 360.0f; float overlay_gpu_y = 12.0f; float overlay_ram_x = 560.0f; float overlay_ram_y = 12.0f; float overlay_ip_x = 740.0f; float overlay_ip_y = 12.0f; float overlay_fan_x = 960.0f; float overlay_fan_y = 12.0f; float overlay_fps_x = 40.0f; float overlay_fps_y = 12.0f; }; struct Metrics { bool enabled = true; bool show_fps = true; bool show_cpu = true; bool show_gpu = true; bool show_ram = true; bool show_ip = false; bool show_fan = false; bool per_core_cpu = false; int font_size_pt = static_cast(kFontH); /* Must match onion::kOverlayMetric* / kOverlayOrderDefault. */ std::array order{kMetricFps, kMetricCpu, kMetricGpu, kMetricMemory, kMetricIp, kMetricFan}; }; inline void normalize_metric_order(std::array &order) { bool seen[kMetricCount] = {}; std::array out{}; int n = 0; for (int metric : order) { if (metric < 0 || metric >= kMetricCount || seen[metric]) continue; seen[metric] = true; out[n++] = metric; } for (int metric = 0; metric < kMetricCount; ++metric) { if (seen[metric]) continue; out[n++] = metric; } order = out; } inline bool valid_screen_dimension(float value) { return std::isfinite(value) && value > 1.0f; } inline Layout compute_overlay_layout(float screen_w, float screen_h, BarEdge edge, BarAlign align, const Metrics &metrics) { Layout out{}; const int font_pt = metrics.font_size_pt > 0 ? metrics.font_size_pt : static_cast(kFontH); const float scale = static_cast(font_pt) / kFontH; const float gap = kGap * scale; out.bar_h = static_cast(font_pt) + kBarExtra; out.label_margin_top = kTextTopInset; out.overlay_cpu_x = kOffscreen; out.overlay_gpu_x = kOffscreen; out.overlay_ram_x = kOffscreen; out.overlay_ip_x = kOffscreen; out.overlay_fan_x = kOffscreen; out.overlay_fps_x = kOffscreen; if (!valid_screen_dimension(screen_w) || !valid_screen_dimension(screen_h)) { return out; } out.screen_w = screen_w; out.screen_h = screen_h; out.bar_x = 0.0f; out.bar_w = screen_w; out.bar_y = (edge == BarEdge::Bottom) ? (screen_h - out.bar_h) : 0.0f; const bool show_cpu = metrics.enabled && (metrics.show_cpu || metrics.per_core_cpu); const bool show_gpu = metrics.enabled && metrics.show_gpu; const bool show_ram = metrics.enabled && metrics.show_ram; const bool show_ip = metrics.enabled && metrics.show_ip; const bool show_fan = metrics.enabled && metrics.show_fan; const bool show_fps = metrics.enabled && metrics.show_fps; const float cpu_w = (metrics.per_core_cpu ? kCpuAllWidth : kCpuAvgWidth) * scale; struct Slot { bool on; float width; float *x; float *y; }; Slot by_metric[kMetricCount] = { {show_fps, kFpsWidth * scale, &out.overlay_fps_x, &out.overlay_fps_y}, {show_cpu, cpu_w, &out.overlay_cpu_x, &out.overlay_cpu_y}, {show_gpu, kGpuWidth * scale, &out.overlay_gpu_x, &out.overlay_gpu_y}, {show_ram, kRamWidth * scale, &out.overlay_ram_x, &out.overlay_ram_y}, {show_ip, kIpWidth * scale, &out.overlay_ip_x, &out.overlay_ip_y}, {show_fan, kFanWidth * scale, &out.overlay_fan_x, &out.overlay_fan_y}, }; std::array order = metrics.order; normalize_metric_order(order); float content_w = 0.0f; int visible = 0; for (int metric : order) { const Slot &slot = by_metric[metric]; if (!slot.on) { continue; } if (visible++) { content_w += gap; } content_w += slot.width; } float x = pack_origin(screen_w, content_w, align); for (int metric = 0; metric < kMetricCount; ++metric) { *by_metric[metric].y = out.bar_y; *by_metric[metric].x = kOffscreen; } for (int metric : order) { Slot &slot = by_metric[metric]; *slot.y = out.bar_y; if (!slot.on || content_w <= 0.0f) { *slot.x = kOffscreen; continue; } *slot.x = x; x += slot.width + gap; } return out; } } // namespace onion::overlay