From 6931f03120d395a6c40d9437b19184dc55661fcb Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Thu, 12 Dec 2019 20:46:17 +0100 Subject: [PATCH] [hud] Add new HUD item abstraction Allows for a cleaner and more flexible implementation of new HUD elements. The old implementation was not intended to support quite as many elements as it does, and now there is some need for API-specific HUD elements. --- src/dxvk/hud/dxvk_hud.cpp | 5 +- src/dxvk/hud/dxvk_hud.h | 14 +++++ src/dxvk/hud/dxvk_hud_item.cpp | 61 ++++++++++++++++++++ src/dxvk/hud/dxvk_hud_item.h | 102 +++++++++++++++++++++++++++++++++ src/dxvk/meson.build | 1 + 5 files changed, 182 insertions(+), 1 deletion(-) create mode 100644 src/dxvk/hud/dxvk_hud_item.cpp create mode 100644 src/dxvk/hud/dxvk_hud_item.h 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', ])