wpf3d游戏引擎下的AssetRegister.cs实现

发布于:2025-06-13 ⋅ 阅读:(23) ⋅ 点赞:(0)

1.AssetRegister.cs

using PrimalEditor.Common;
using PrimalEditor.Utilities;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;

namespace PrimalEditor.Content
{
    static class AssetRegistry
    {
        private static readonly DelayEventTimer _refreshTimer = new DelayEventTimer(TimeSpan.FromMicroseconds(250));
        private static readonly Dictionary<string, AssetInfo> _assetDictionary = new Dictionary<string, AssetInfo>();
        private static readonly ObservableCollection<AssetInfo> _assets = new ObservableCollection<AssetInfo>();
        private static readonly FileSystemWatcher _contentWatcher = new FileSystemWatcher()
        {
            IncludeSubdirectories = true,
            Filter = "",
            NotifyFilter = NotifyFilters.CreationTime |
                            NotifyFilters.DirectoryName |
                            NotifyFilters.FileName | 
                            NotifyFilters.LastWrite    

        };

        public static ReadOnlyObservableCollection<AssetInfo> Assets { get; } = new ReadOnlyObservableCollection<AssetInfo>(_assets);

        private static void RegisterAllAssets(string path) 
        {
            Debug.Assert(Directory.Exists(path));
            foreach (var entry in Directory.GetFileSystemEntries(path))
            {
                if (ContentHelper.IsDirectory(entry))
                {
                    RegisterAllAssets(entry);
                }
                else
                { 
                    RegisterAsset(entry);

                }
                
            }
        
        
        }

        private static void RegisterAsset(string file)
        {
            Debug.Assert(File.Exists(file));
            try
            {
                var fileInfo = new FileInfo(file);
                if (!_assetDictionary.ContainsKey(file) ||
                    _assetDictionary[file].RegisterTime.IsOlder(fileInfo.LastWriteTime)) 
                {
                    var info = Asset.GetAssetInfo(file);
                    Debug.Assert(info != null);
                    info.RegisterTime = DateTime.Now;
                    _assetDictionary[file] = info;

                    Debug.Assert(_assetDictionary.ContainsKey(file));
                    _assets.Add(_assetDictionary[file]);

                }
                
            
            
            }catch (Exception ex) 
            {

                Debug.WriteLine(ex.Message);
            
            }

        }

        private static void UnRegisterAsset(string file) 
        {
            if (_assetDictionary.ContainsKey(file)) 
            {

                _assets.Remove(_assetDictionary[file]);
                _assetDictionary.Remove(file);
            
            
            }
            
        
        
        }


        private static async void OnContentModified(object sender, FileSystemEventArgs e)
        {
            if (Path.GetExtension(e.FullPath) != Asset.AssetFileExtension) return;

            await Application.Current.Dispatcher.BeginInvoke(new Action(() => {
            
                _refreshTimer.Trigger();

            }));

        }

        private static void Refresh(object? sender, DelayEventTimerArgs e)
        {
            foreach (var item in e.Data) 
            {

                if (!(item is FileSystemEventArgs eventArgs)) continue;

                if (eventArgs.ChangeType == WatcherChangeTypes.Deleted)
                {

                    UnRegisterAsset(eventArgs.FullPath);

                }
                else 
                {
                    RegisterAsset(eventArgs.FullPath);
                    if (eventArgs.ChangeType == WatcherChangeTypes.Renamed) 
                    {
                        
                        _assetDictionary.Keys.Where(key=>!File.Exists(key)).ToList().ForEach(file => UnRegisterAsset(file));
                    
                    
                    }
                
                
                
                }
            
            
            
            
            
            }
        }

        public static void Clear() 
        {
            _contentWatcher.EnableRaisingEvents = false;
            _assetDictionary.Clear();
            _assets.Clear();
        
        
        }
        public static void Reset(string contentFolder) 
        {

            Clear();
            Debug.Assert(Directory.Exists(contentFolder));
            RegisterAllAssets(contentFolder);
            _contentWatcher.Path = contentFolder;   
            _contentWatcher.EnableRaisingEvents = true;    
        
        }


        public static AssetInfo GetAssetInfo(string file) => _assetDictionary.ContainsKey(file) ? _assetDictionary[file] : null;
        public static AssetInfo GetAssetinfo(Guid guid) => _assets.FirstOrDefault(x => x.Guid == guid);

        static AssetRegistry() 
        {
            _contentWatcher.Changed += OnContentModified;
            _contentWatcher.Created += OnContentModified;
            _contentWatcher.Deleted += OnContentModified;
            _contentWatcher.Renamed += OnContentModified;

            _refreshTimer.Triggered += Refresh;

        }

        
    }
}