#pragma once #include "Rendering/Host/HostFwd.h" #include #include #include #include #include #include #include #include #include #include #include namespace XCEngine::UI::Editor::App { enum class BuiltInIconKind : std::uint8_t { Folder = 0, GameObject, Scene, CameraGizmo, DirectionalLightGizmo, PointLightGizmo, SpotLightGizmo, PlayButton, PauseButton, StepButton }; class BuiltInIcons { public: void Initialize(Rendering::Host::UiTextureHost& renderer); void Shutdown(); void BeginFrame(); const ::XCEngine::UI::UITextureHandle& Resolve(BuiltInIconKind kind) const; const ::XCEngine::UI::UITextureHandle* ResolveAssetPreview( const std::filesystem::path& assetPath, const std::filesystem::path& projectRoot); const std::string& GetLastError() const; struct LoadedTexturePixels { std::vector rgbaPixels = {}; int width = 0; int height = 0; }; struct SourceFileFingerprint { std::uint64_t fileSize = 0; std::int64_t lastWriteTimeTicks = 0; bool IsValid() const { return fileSize > 0 && lastWriteTimeTicks != 0; } bool operator==(const SourceFileFingerprint&) const = default; }; struct PreviewDecodeJob { std::string key = {}; std::filesystem::path filePath = {}; std::filesystem::path cacheFilePath = {}; std::string relativePathKey = {}; std::uint64_t fileSize = 0; std::int64_t lastWriteTimeTicks = 0; bool useDiskCache = false; }; struct PreviewDecodeResult { std::string key = {}; LoadedTexturePixels pixels = {}; std::uint64_t fileSize = 0; std::int64_t lastWriteTimeTicks = 0; bool success = false; }; struct CachedAssetPreview { ::XCEngine::UI::UITextureHandle texture = {}; std::unique_ptr decodedPixels = {}; SourceFileFingerprint sourceFingerprint = {}; bool decodeQueued = false; bool loadFailed = false; std::int64_t lastUsedFrame = -1; std::int64_t lastSourceValidationFrame = -1; }; private: void ResetAssetPreviewCache(); void StartPreviewWorkers(); void StopPreviewWorkers(); void PreviewWorkerMain(); void DrainPreviewDecodeResults(); void MaintainPreviewRuntimeState(); void InvalidateAssetPreview(CachedAssetPreview& preview); bool RefreshAssetPreviewSourceFingerprint( const std::filesystem::path& filePath, CachedAssetPreview& preview); bool QueuePreviewDecode( const std::string& key, const std::filesystem::path& filePath, const SourceFileFingerprint& sourceFingerprint, const std::filesystem::path& projectRoot); CachedAssetPreview* GetOrCreateAssetPreview( const std::filesystem::path& assetPath, const std::filesystem::path& projectRoot); void PruneAssetPreviewCache(); Rendering::Host::UiTextureHost* m_renderer = nullptr; ::XCEngine::UI::UITextureHandle m_folderIcon = {}; ::XCEngine::UI::UITextureHandle m_gameObjectIcon = {}; ::XCEngine::UI::UITextureHandle m_sceneIcon = {}; ::XCEngine::UI::UITextureHandle m_cameraGizmoIcon = {}; ::XCEngine::UI::UITextureHandle m_directionalLightGizmoIcon = {}; ::XCEngine::UI::UITextureHandle m_pointLightGizmoIcon = {}; ::XCEngine::UI::UITextureHandle m_spotLightGizmoIcon = {}; ::XCEngine::UI::UITextureHandle m_playButtonIcon = {}; ::XCEngine::UI::UITextureHandle m_pauseButtonIcon = {}; ::XCEngine::UI::UITextureHandle m_stepButtonIcon = {}; std::unordered_map m_assetPreviews = {}; std::vector m_previewWorkers = {}; std::deque m_previewDecodeQueue = {}; std::deque m_previewDecodeResults = {}; std::mutex m_previewQueueMutex = {}; std::condition_variable m_previewQueueEvent = {}; bool m_previewWorkersRunning = false; std::size_t m_pendingPreviewDecodeJobs = 0u; std::int64_t m_frameIndex = 0; int m_previewLoadsThisFrame = 0; std::string m_lastError = {}; }; } // namespace XCEngine::UI::Editor::App