Editor/AssetBrowserAddon/locations/FilteredLocation.cs
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Editor;
using Sandbox;
namespace Sandbox.AssetBrowserAddon;
/// <summary>
/// Location implementation that filters assets based on a serialized definition.
/// </summary>
public record FilteredLocation : LocalAssetBrowser.Location
{
public CustomLocationDefinition Definition { get; }
public override bool IsAggregate => true;
public FilteredLocation(CustomLocationDefinition definition)
: base(definition?.Name ?? "Custom Location",
string.IsNullOrWhiteSpace(definition?.Icon) ? "extension" : definition.Icon)
{
Definition = definition ?? throw new ArgumentNullException(nameof(definition));
Path = $"@custom/{Definition.Id}";
Icon = string.IsNullOrWhiteSpace(Definition.Icon) ? Icon : Definition.Icon;
}
public override bool CanGoUp() => false;
public override IEnumerable<LocalAssetBrowser.Location> GetDirectories() => Enumerable.Empty<LocalAssetBrowser.Location>();
public override IEnumerable<FileInfo> GetFiles()
{
return AssetSystem.All
.Where(IsMatch)
.OrderBy(asset => asset.RelativePath, StringComparer.OrdinalIgnoreCase)
.Select(asset => new FileInfo(asset.AbsolutePath));
}
private bool IsMatch(Asset asset)
{
var rel = Normalize(asset.RelativePath);
var abs = Normalize(asset.AbsolutePath); // add this
if (asset is null)
return false;
if (Definition.ProjectAssetsOnly)
{
var projectRoot = Normalize(Project.Current?.GetRootPath());
if (!string.IsNullOrEmpty(projectRoot))
{
var assetPath = Normalize(asset.AbsolutePath);
if (!assetPath.StartsWith(projectRoot, StringComparison.OrdinalIgnoreCase))
return false;
}
}
if (Definition.AssetTypes is { Count: > 0 })
{
var extension = NormalizeExtension(asset.AssetType?.FileExtension ?? System.IO.Path.GetExtension(asset.AbsolutePath));
var matchesType = Definition.AssetTypes.Any(tag =>
string.Equals(tag, extension, StringComparison.OrdinalIgnoreCase));
if (!matchesType)
return false;
}
var relative = Normalize(asset.RelativePath);
// include
if (Definition.IncludeFolders is { Count: > 0 })
{
var inc = Definition.IncludeFolders.Any(p =>
{
var pat = Normalize(p);
return rel.Contains(pat) || abs.Contains(pat);
});
if (!inc) return false;
}
// exclude
if (Definition.ExcludeFolders is { Count: > 0 })
{
var exc = Definition.ExcludeFolders.Any(p =>
{
var pat = Normalize(p);
return rel.Contains(pat) || abs.Contains(pat);
});
if (exc) return false;
}
return true;
}
private static string Normalize(string value)
{
if (string.IsNullOrWhiteSpace(value))
return string.Empty;
return value.Replace('\\', '/').ToLowerInvariant();
}
private static string NormalizeExtension(string value)
{
if (string.IsNullOrWhiteSpace(value))
return string.Empty;
return value.Trim().TrimStart('.').ToLowerInvariant();
}
}