11using CommunityToolkit . Mvvm . ComponentModel ;
2- using Stride . Core . Shaders . Ast ;
3- using Stride . ShaderParser ;
42using System ;
53using System . Collections . Generic ;
6- using System . Diagnostics ;
74using System . IO ;
85using System . Linq ;
96using System . Text . Json ;
10- using System . Text . RegularExpressions ;
117using System . Windows ;
128
139namespace StrideShaderExplorer
@@ -18,15 +14,24 @@ public enum StrideSourceDirMode
1814 Dev
1915 }
2016
17+ public enum SearchMode
18+ {
19+ FilesAndMembers ,
20+ FilenameOnly ,
21+ MembersOnly
22+ }
23+
2124 public class MainViewModel : ObservableRecipient
2225 {
2326 private const string StrideEnvironmentVariable = "StrideDir" ;
2427 private const string NugetEnvironmentVariable = "NUGET_PACKAGES" ;
2528
2629 private readonly NuGetDownloader _nugetDownloader = new ( ) ;
30+ private readonly ShaderRepository _shaderRepository = new ( ) ;
31+ private readonly ShaderTreeBuilder _shaderTreeBuilder ;
2732
2833 private string _filterText ;
29- private bool _directParentsOnly = true ;
34+ private SearchMode _searchMode = SearchMode . FilesAndMembers ;
3035 private ShaderViewModel _selectedShader ;
3136 private IReadOnlyList < string > _paths ;
3237
@@ -36,53 +41,11 @@ public List<string> AdditionalPaths
3641 set ;
3742 }
3843
39- public Dictionary < string , ShaderViewModel > shaders = new Dictionary < string , ShaderViewModel > ( ) ;
40- public Dictionary < string , Dictionary < ShaderViewModel , MemberList > > members = new Dictionary < string , Dictionary < ShaderViewModel , MemberList > > ( ) ;
41- public Dictionary < string , ShaderViewModel > ShaderMap => shaders ;
44+ public IReadOnlyDictionary < string , ShaderViewModel > ShaderMap => _shaderRepository . Shaders ;
4245
4346 public bool FindMember ( string name , ShaderViewModel shader , out MemberList mems , out List < ShaderViewModel > scopedShaders )
4447 {
45- mems = null ;
46- scopedShaders = null ;
47- var result = members . TryGetValue ( name , out var memberCandidates ) ;
48-
49- if ( result )
50- {
51- // defined locally?
52- if ( memberCandidates . TryGetValue ( shader , out mems ) )
53- {
54-
55- }
56-
57- //find base shaders that defines the member, could be multiple for method overrides
58- scopedShaders = new List < ShaderViewModel > ( ) ;
59- var definingShader = shader ;
60- foreach ( var baseShader in shader . BaseShaders )
61- {
62-
63- if ( memberCandidates . TryGetValue ( baseShader , out var ms ) )
64- {
65- //find highest definition in hierarchy
66- if ( definingShader . BaseShaders . Contains ( baseShader ) )
67- {
68- mems = ms ;
69- }
70-
71- scopedShaders . Add ( baseShader ) ;
72- }
73- }
74-
75- //also add derived shaders
76- foreach ( var derivedShader in shader . DerivedShaders )
77- {
78- if ( memberCandidates . TryGetValue ( derivedShader , out var _ ) )
79- {
80- scopedShaders . Add ( derivedShader ) ;
81- }
82- }
83- }
84-
85- return result ;
48+ return _shaderRepository . FindMember ( name , shader , out mems , out scopedShaders ) ;
8649 }
8750
8851 /// <summary>
@@ -106,13 +69,29 @@ public string FilterText
10669 }
10770 }
10871
72+ public SearchMode SearchMode
73+ {
74+ get { return _searchMode ; }
75+ set
76+ {
77+ if ( SetProperty ( ref _searchMode , value ) )
78+ UpdateFiltering ( ) ;
79+ }
80+ }
81+
82+ public IEnumerable < SearchMode > SearchModeOptions => Enum . GetValues < SearchMode > ( ) ;
83+
10984 public bool DirectParentsOnly
11085 {
111- get { return _directParentsOnly ; }
86+ get { return _shaderTreeBuilder . DirectParentsOnly ; }
11287 set
11388 {
114- if ( SetProperty ( ref _directParentsOnly , value ) )
89+ if ( _shaderTreeBuilder . DirectParentsOnly != value )
90+ {
91+ _shaderTreeBuilder . DirectParentsOnly = value ;
92+ OnPropertyChanged ( ) ;
11593 Refresh ( ) ;
94+ }
11695 }
11796 }
11897
@@ -182,7 +161,7 @@ internal void Refresh()
182161 // If no Stride packages found in nuget, try vvvv's packs folder
183162 if ( paths . Count == 0 )
184163 {
185- var vvvvPaths = DetectVvvvStridePackages ( ) ;
164+ var vvvvPaths = VvvvPathResolver . Instance . GetStridePackagePaths ( ) ;
186165 if ( vvvvPaths . Count > 0 )
187166 paths = vvvvPaths ;
188167 }
@@ -276,7 +255,7 @@ public IReadOnlyList<string> Paths
276255 {
277256 try
278257 {
279- RootShaders = BuildShaderTree ( ) . OrderBy ( s => s . Name , StringComparer . OrdinalIgnoreCase ) . ToList ( ) ;
258+ RootShaders = _shaderTreeBuilder . BuildTree ( value ) ;
280259 OnPropertyChanged ( nameof ( RootShaders ) ) ;
281260 OnPropertyChanged ( nameof ( AllShaders ) ) ;
282261 UpdateFiltering ( ) ;
@@ -294,12 +273,14 @@ public IReadOnlyList<string> Paths
294273
295274 public MainViewModel ( )
296275 {
276+ _shaderTreeBuilder = new ShaderTreeBuilder ( _shaderRepository ) ;
277+
297278 AdditionalPaths = Properties . UserSettings . Default . AdditionalPaths . Split ( ';' ) . ToList ( ) ;
298279
299280 // Auto-detect vvvv paths on first run
300281 if ( ! Properties . UserSettings . Default . VvvvPathsDetected )
301282 {
302- var vvvvPaths = DetectVvvvShaderPaths ( ) ;
283+ var vvvvPaths = VvvvPathResolver . Instance . GetVLStrideShaderPaths ( ) ;
303284 foreach ( var path in vvvvPaths )
304285 {
305286 if ( ! AdditionalPaths . Contains ( path ) )
@@ -349,22 +330,12 @@ private bool DownloadStridePackages()
349330 return false ;
350331 }
351332
352- private List < string > DetectVvvvStridePackages ( )
353- {
354- return VvvvPathResolver . Instance . GetStridePackagePaths ( ) ;
355- }
356-
357- public List < string > DetectVvvvShaderPaths ( )
358- {
359- return VvvvPathResolver . Instance . GetVLStrideShaderPaths ( ) ;
360- }
361-
362333 public void ExportShaderHierarchy ( string filePath )
363334 {
364335 var export = new HierarchyExport
365336 {
366337 ExportedAt = DateTime . Now . ToString ( "o" ) ,
367- ShaderCount = shaders . Count ,
338+ ShaderCount = _shaderRepository . Count ,
368339 RootShaders = RootShaders . Select ( ShaderToExport ) . ToList ( )
369340 } ;
370341
@@ -394,9 +365,36 @@ private void UpdateFiltering()
394365 {
395366 foreach ( var shader in AllShaders )
396367 {
397- shader . IsVisible = string . IsNullOrEmpty ( _filterText ) ||
398- shader . Name . ToLower ( ) . Contains ( _filterText . ToLower ( ) ) ;
399- shader . IsExpanded = shader . DerivedShaders . Any ( o => o . IsVisible ) ;
368+ if ( string . IsNullOrEmpty ( _filterText ) )
369+ {
370+ shader . IsVisible = true ;
371+ // Don't change IsExpanded when filter is empty
372+ }
373+ else
374+ {
375+ var lowerFilter = _filterText . ToLower ( ) ;
376+ bool matchesName = shader . Name . ToLower ( ) . Contains ( lowerFilter ) ;
377+ bool matchesMember = false ;
378+
379+ if ( _searchMode != SearchMode . FilenameOnly && shader . ParsedShader != null )
380+ {
381+ matchesMember = shader . ParsedShader . Variables ? . Any ( v =>
382+ v . Name ? . Text ? . ToLower ( ) . Contains ( lowerFilter ) == true ) == true ||
383+ shader . ParsedShader . Methods ? . Any ( m =>
384+ m . Name ? . Text ? . ToLower ( ) . Contains ( lowerFilter ) == true ) == true ;
385+ }
386+
387+ shader . IsVisible = _searchMode switch
388+ {
389+ SearchMode . FilesAndMembers => matchesName || matchesMember ,
390+ SearchMode . FilenameOnly => matchesName ,
391+ SearchMode . MembersOnly => matchesMember ,
392+ _ => matchesName || matchesMember
393+ } ;
394+
395+ // Auto-expand parents of visible items only when filtering
396+ shader . IsExpanded = shader . DerivedShaders . Any ( o => o . IsVisible ) ;
397+ }
400398 }
401399 }
402400
@@ -421,88 +419,6 @@ private static IEnumerable<ShaderViewModel> ShadersInPostOrder(ShaderViewModel s
421419 yield return shader ;
422420 }
423421
424- private IEnumerable < ShaderViewModel > BuildShaderTree ( )
425- {
426- var files = Paths . Where ( p => ! string . IsNullOrWhiteSpace ( p ) && Directory . Exists ( p ) )
427- . SelectMany ( path => Directory . GetFiles ( path , "*.sdsl" , SearchOption . AllDirectories ) ) ;
428-
429- shaders . Clear ( ) ;
430- var duplicates = new Dictionary < string , ShaderViewModel > ( ) ;
431-
432- foreach ( var file in files )
433- {
434- var name = Path . GetFileNameWithoutExtension ( file ) ;
435- if ( ! shaders . ContainsKey ( name ) )
436- shaders [ name ] = new ShaderViewModel { Path = file , Name = name } ;
437- else
438- duplicates [ name ] = new ShaderViewModel { Path = file , Name = name } ;
439- }
440-
441- foreach ( var shader in shaders . Values )
442- {
443- if ( EffectUtils . TryParseEffect ( shader . Name , shaders , out var parsedShader ) )
444- {
445- var baseShaderNames = parsedShader . BaseShaders . Select ( s => s . ShaderClass . Name . Text ) . ToList ( ) ;
446- shader . ParsedShader = parsedShader ;
447-
448- // get all declrarations in this shader
449- foreach ( var m in parsedShader . ShaderClass . Members . OfType < IDeclaration > ( ) ?? Enumerable . Empty < IDeclaration > ( ) )
450- {
451- var mn = m . Name . Text ;
452- if ( string . IsNullOrWhiteSpace ( mn ) )
453- {
454- continue ;
455- }
456-
457- if ( ! members . TryGetValue ( mn , out var memberCandidates ) )
458- {
459- memberCandidates = new Dictionary < ShaderViewModel , MemberList > ( ) ;
460- }
461-
462- if ( ! memberCandidates . TryGetValue ( shader , out var mems ) )
463- {
464- mems = new MemberList ( ) ;
465- }
466-
467- mems . Add ( new MemberViewModel ( mn , m ) ) ;
468-
469- memberCandidates [ shader ] = mems ;
470- members [ mn ] = memberCandidates ;
471- }
472-
473- if ( baseShaderNames . Count > 0 )
474- {
475- var baseShaders = baseShaderNames
476- . Select ( s => shaders . TryGetValue ( s , out var b ) ? b : null )
477- . Where ( s => s != null ) ;
478-
479- foreach ( var baseShader in baseShaders )
480- {
481- shader . BaseShaders . Add ( baseShader ) ;
482- baseShader . DerivedShaders . Add ( shader ) ;
483- if ( _directParentsOnly )
484- {
485- if ( parsedShader . ShaderClass . BaseClasses . FirstOrDefault ( bc => bc . Name . Text == baseShader . Name ) != null )
486- {
487- baseShader . TreeViewChildren . Add ( shader ) ;
488- }
489- }
490- else
491- {
492- baseShader . TreeViewChildren . Add ( shader ) ;
493- }
494- }
495- }
496- else
497- {
498- yield return shader ;
499- }
500- }
501-
502- }
503-
504- Debug . WriteLine ( $ "Found { shaders . Count } shaders") ;
505- }
506422 }
507423
508424 public class ShaderExport
0 commit comments