#pragma once #include "Core/IEditorContext.h" #include #include #include #include #include #include #include namespace XCEngine { namespace Editor { class ProjectAssetWatcher { public: ~ProjectAssetWatcher(); void Attach(const std::string& projectPath); void Detach(); void Update(IEditorContext& context, float dt); private: struct AssetEntryState { bool isDirectory = false; std::uint64_t fileSize = 0; std::uint64_t writeTime = 0; bool operator==(const AssetEntryState& other) const { return isDirectory == other.isDirectory && fileSize == other.fileSize && writeTime == other.writeTime; } }; struct ChangeStats { std::uint32_t added = 0; std::uint32_t modified = 0; std::uint32_t removed = 0; bool HasChanges() const { return added > 0 || modified > 0 || removed > 0; } void Clear() { added = 0; modified = 0; removed = 0; } void Accumulate(const ChangeStats& other) { added += other.added; modified += other.modified; removed += other.removed; } }; using Snapshot = std::unordered_map; void RefreshProjectBinding(const std::string& projectPath); void StartNativeWatcher(); void StopNativeWatcher(); void RunNativeWatcher(void* directoryHandle, std::filesystem::path watchedRoot); void ConsumeNativeChanges(); void ScheduleRefresh(const ChangeStats& changes); void ScanForChanges(); void FlushPendingRefresh(IEditorContext& context); static void BuildSnapshot(const std::filesystem::path& assetsRoot, Snapshot& outSnapshot); static ChangeStats DiffSnapshots(const Snapshot& previousSnapshot, const Snapshot& currentSnapshot); std::string m_projectPath; std::filesystem::path m_assetsRoot; Snapshot m_snapshot; ChangeStats m_pendingChanges; float m_scanCooldownSeconds = 0.0f; float m_nativeRestartCooldownSeconds = 0.0f; float m_debounceSeconds = 0.0f; bool m_hasPendingRefresh = false; std::thread m_nativeWatcherThread; std::mutex m_nativeChangeMutex; ChangeStats m_threadPendingChanges; std::atomic m_nativeWatcherHealthy{false}; std::atomic m_pollingResyncRequested{false}; void* m_nativeStopEvent = nullptr; }; } // namespace Editor } // namespace XCEngine