diff --git a/src/dxvk/hud/dxvk_hud.cpp b/src/dxvk/hud/dxvk_hud.cpp index 22b9e805..8a1371de 100644 --- a/src/dxvk/hud/dxvk_hud.cpp +++ b/src/dxvk/hud/dxvk_hud.cpp @@ -43,6 +43,7 @@ namespace dxvk::hud { void Hud::update() { + m_hudItems.update(); m_hudFramerate.update(); m_hudStats.update(m_device); } @@ -84,8 +85,10 @@ namespace dxvk::hud { void Hud::renderHudElements(const Rc& ctx) { + m_hudItems.render(m_renderer); + HudPos position = { 8.0f, 24.0f }; - + if (m_config.elements.test(HudElement::DxvkVersion)) { m_renderer.drawText(16.0f, { position.x, position.y }, diff --git a/src/dxvk/hud/dxvk_hud.h b/src/dxvk/hud/dxvk_hud.h index 3b702c3b..3f4e5e4f 100644 --- a/src/dxvk/hud/dxvk_hud.h +++ b/src/dxvk/hud/dxvk_hud.h @@ -6,6 +6,7 @@ #include "dxvk_hud_config.h" #include "dxvk_hud_devinfo.h" +#include "dxvk_hud_item.h" #include "dxvk_hud_fps.h" #include "dxvk_hud_renderer.h" #include "dxvk_hud_stats.h" @@ -54,6 +55,18 @@ namespace dxvk::hud { void render( const Rc& ctx, VkExtent2D surfaceSize); + + /** + * \brief Adds a HUD item if enabled + * + * \tparam T The HUD item type + * \param [in] name HUD item name + * \param [in] args Constructor arguments + */ + template + void addItem(const char* name, Args... args) { + m_hudItems.add(name, std::forward(args)...); + } /** * \brief Creates the HUD @@ -81,6 +94,7 @@ namespace dxvk::hud { HudDeviceInfo m_hudDeviceInfo; HudFps m_hudFramerate; HudStats m_hudStats; + HudItemSet m_hudItems; void setupRendererState( const Rc& ctx); diff --git a/src/dxvk/hud/dxvk_hud_item.cpp b/src/dxvk/hud/dxvk_hud_item.cpp new file mode 100644 index 00000000..153f1e0a --- /dev/null +++ b/src/dxvk/hud/dxvk_hud_item.cpp @@ -0,0 +1,61 @@ +#include "dxvk_hud_item.h" + +namespace dxvk::hud { + + HudItem::~HudItem() { + + } + + + void HudItem::update(dxvk::high_resolution_clock::time_point time) { + // Do nothing by default. Some items won't need this. + } + + + HudItemSet::HudItemSet() { + std::string configStr = env::getEnvVar("DXVK_HUD"); + + if (configStr == "full") { + // Just enable everything + m_enableFull = true; + } else if (configStr == "1") { + m_enabled.insert("devinfo"); + m_enabled.insert("fps"); + } else { + std::string::size_type pos = 0; + std::string::size_type end = 0; + + while (pos < configStr.size()) { + end = configStr.find(',', pos); + + if (end == std::string::npos) + end = configStr.size(); + + m_enabled.insert(configStr.substr(pos, end - pos)); + pos = end + 1; + } + } + } + + + HudItemSet::~HudItemSet() { + + } + + + void HudItemSet::update() { + auto time = dxvk::high_resolution_clock::now(); + + for (const auto& item : m_items) + item->update(time); + } + + + void HudItemSet::render(HudRenderer& renderer) { + HudPos position = { 8.0f, 8.0f }; + + for (const auto& item : m_items) + position = item->render(renderer, position); + } + +} diff --git a/src/dxvk/hud/dxvk_hud_item.h b/src/dxvk/hud/dxvk_hud_item.h new file mode 100644 index 00000000..eccb054f --- /dev/null +++ b/src/dxvk/hud/dxvk_hud_item.h @@ -0,0 +1,102 @@ +#pragma once + +#include +#include +#include + +#include "../../util/util_time.h" + +#include "dxvk_hud_renderer.h" + +namespace dxvk::hud { + + /** + * \brief HUD item + * + * A single named item in the HUD that + * can be enabled by the user. + */ + class HudItem : public RcObject { + + public: + + virtual ~HudItem(); + + /** + * \brief Updates the HUD item + * \param [in] time Current time + */ + virtual void update( + dxvk::high_resolution_clock::time_point time); + + /** + * \brief Renders the HUD + * + * \param [in] renderer HUD renderer + * \param [in] position Base offset + * \returns Base offset for next item + */ + virtual HudPos render( + HudRenderer& renderer, + HudPos position) = 0; + + }; + + + /** + * \brief HUD item set + * + * Manages HUD items. + */ + class HudItemSet { + + public: + + HudItemSet(); + + ~HudItemSet(); + + /** + * \brief Updates the HUD + * Updates all enabled HUD items. + */ + void update(); + + /** + * \brief Renders the HUD + * + * \param [in] renderer HUD renderer + * \returns Base offset for next item + */ + void render( + HudRenderer& renderer); + + /** + * \brief Creates a HUD item if enabled + * + * \tparam T The HUD item type + * \param [in] name HUD item name + * \param [in] args Constructor arguments + */ + template + void add(const char* name, Args... args) { + bool enable = m_enableFull; + + if (!enable) { + auto entry = m_enabled.find(name); + enable = entry != m_enabled.end(); + } + + if (enable) + m_items.push_back(new T(std::forward(args)...)); + } + + private: + + bool m_enableFull = false; + std::unordered_set m_enabled; + std::vector> m_items; + + }; + +} \ No newline at end of file diff --git a/src/dxvk/meson.build b/src/dxvk/meson.build index 149ed757..09730b84 100644 --- a/src/dxvk/meson.build +++ b/src/dxvk/meson.build @@ -106,6 +106,7 @@ dxvk_src = files([ 'hud/dxvk_hud_devinfo.cpp', 'hud/dxvk_hud_font.cpp', 'hud/dxvk_hud_fps.cpp', + 'hud/dxvk_hud_item.cpp', 'hud/dxvk_hud_renderer.cpp', 'hud/dxvk_hud_stats.cpp', ])