-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathLithTechModelPartGrouper.cs
More file actions
92 lines (79 loc) · 2.88 KB
/
LithTechModelPartGrouper.cs
File metadata and controls
92 lines (79 loc) · 2.88 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
using System.IO;
namespace CFRezManager;
internal static class LithTechModelPartGrouper
{
public static List<ExplorerItem> ExpandNumberedSiblingParts(IEnumerable<ExplorerItem> items)
{
var expanded = new List<ExplorerItem>();
var seen = new HashSet<ExplorerItem>();
foreach (ExplorerItem item in items)
{
foreach (ExplorerItem part in ExpandNumberedSiblingParts(item))
{
if (seen.Add(part))
{
expanded.Add(part);
}
}
}
return expanded;
}
public static List<ExplorerItem> ExpandNumberedSiblingParts(ExplorerItem item)
{
if (!IsModelFile(item) || item.Parent is null)
{
return [item];
}
string baseStem = GetNumberedPartBase(Path.GetFileNameWithoutExtension(item.Name));
List<ExplorerItem> siblings = item.Parent.Children
.Where(IsModelFile)
.Where(candidate => string.Equals(
GetNumberedPartBase(Path.GetFileNameWithoutExtension(candidate.Name)),
baseStem,
StringComparison.OrdinalIgnoreCase))
.OrderBy(candidate => GetNumberedPartOrder(Path.GetFileNameWithoutExtension(candidate.Name), baseStem))
.ThenBy(candidate => candidate.Name, StringComparer.OrdinalIgnoreCase)
.ToList();
return siblings.Count > 1 ? siblings : [item];
}
public static string GetNumberedPartBase(string stem)
{
return TryStripNumericSuffix(stem, out string? baseStem)
? baseStem!
: stem;
}
public static bool TryStripNumericSuffix(string stem, out string? baseStem)
{
baseStem = null;
int separatorIndex = stem.LastIndexOf('_');
if (separatorIndex <= 0 || separatorIndex + 1 >= stem.Length)
{
return false;
}
ReadOnlySpan<char> suffix = stem.AsSpan(separatorIndex + 1);
if (!suffix.ToString().All(char.IsDigit))
{
return false;
}
baseStem = stem[..separatorIndex];
return !string.IsNullOrWhiteSpace(baseStem);
}
private static int GetNumberedPartOrder(string stem, string baseStem)
{
if (string.Equals(stem, baseStem, StringComparison.OrdinalIgnoreCase))
{
return 0;
}
return TryStripNumericSuffix(stem, out string? stripped) &&
string.Equals(stripped, baseStem, StringComparison.OrdinalIgnoreCase) &&
int.TryParse(stem[(stem.LastIndexOf('_') + 1)..], out int order)
? order
: int.MaxValue;
}
private static bool IsModelFile(ExplorerItem item)
{
return item.IsFile &&
(LithTechModelDecoder.IsCandidate(item.FileExtension) ||
LithTechWorldDatDecoder.IsCandidate(item.FileExtension));
}
}