#pragma once #include #include #include #include #include #include class OffscreenQuickRenderer; class Overlay; class QQmlEngine; class QQuickWindow; class RenderBackend; class Surface; class VrRuntime; // Configuration of one view of the app (see DashboardApplication::addSurface). // Members not given (designated initializers) keep their defaults. struct SurfaceConfig { // Unique within the app; the overlay key is ".", or the app key // itself for an empty id (allowed for one surface). QString id = {}; // Root type in the app's QML module (required). QString qmlRootType = {}; // Tab name; default: the app's display name. QString displayName = {}; // Texture size in pixels; default: AppConfig (VRDASH_TEXTURE_*). QSize textureSize = {}; // Dashboard tab icon; default: the display name's initials. std::function thumbnail = {}; }; // One view of the app: its QML scene, rendered offscreen by its own renderer // and render backend, shown in SteamVR by its overlay (a dashboard tab). // A component: configure it (SurfaceConfig) and connect to its signals; it is // created and driven by DashboardApplication. // // Lifetime rule (enforced by DashboardApplication): the overlay goes before // SteamVR shuts down, SteamVR shuts down before the render backend goes. class Surface : public QObject { Q_OBJECT public: Surface(SurfaceConfig config, QString overlayKey, QString displayName, QSize textureSize, QObject* parent = nullptr); ~Surface() override; const SurfaceConfig& config() const { return m_config; } QString id() const { return m_config.id; } QString overlayKey() const { return m_overlayKey; } QString displayName() const { return m_displayName; } QSize textureSize() const { return m_textureSize; } RenderBackend* backend() const { return m_backend.get(); } OffscreenQuickRenderer* renderer() const { return m_renderer.get(); } QQuickWindow* window() const; Overlay* overlay() const { return m_overlay.get(); } // overlay mode only bool isVisible() const; // --- Driven by DashboardApplication --- // Takes the initialized backend and creates the renderer (no QML yet). void setBackend(std::unique_ptr backend, int maxFps); bool loadQml(QQmlEngine& engine, const QString& qmlModule, QString* error); bool createDashboardOverlay(VrRuntime& runtime, const QImage& thumbnail, QString* error); void destroyOverlay(); signals: void visibilityChanged(bool visible); // Became the surface the user interacts with: the laser entered it, or // its dashboard tab was opened. void activated(); private: SurfaceConfig m_config; QString m_overlayKey; QString m_displayName; QSize m_textureSize; // Destruction order: overlay, renderer, backend. std::unique_ptr m_backend; std::unique_ptr m_renderer; std::unique_ptr m_overlay; };